Last active
July 2, 2025 23:07
-
-
Save jadsongmatos/09378f03c5599bb792f6f86a414015cf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 300 es | |
precision highp float; | |
out vec4 out_color; | |
in vec2 uv; | |
uniform float u_time; | |
uniform vec2 u_resolution; | |
/* Hash e ruído avançado */ | |
vec2 hash22(vec2 p) { | |
return fract(sin(vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)))) * 43758.5453); | |
} | |
float worley(vec2 p) { | |
vec2 i = floor(p); | |
vec2 f = fract(p); | |
float minDist = 1.0; | |
for(int y=-1; y<=1; y++) { | |
for(int x=-1; x<=1; x++) { | |
vec2 neighbor = vec2(x,y); | |
vec2 point = hash22(i + neighbor); | |
float dist = length(neighbor + point - f); | |
minDist = min(minDist, dist); | |
} | |
} | |
return minDist; | |
} | |
float fbm(vec2 p) { | |
float total = 0.0; | |
float amp = 0.5; | |
vec2 shift = vec2(1.0, 1.0); | |
for(int i=0; i<6; i++) { | |
total += worley(p) * amp; | |
p = p * 2.03 + shift; | |
amp *= 0.5; | |
shift *= 2.0; | |
} | |
return total; | |
} | |
/* Constantes realistas */ | |
const float RADIUS = 0.06; | |
const float TRENCH_DEPTH = 0.65; | |
const float RIDGE_RATIO = 0.25; | |
const int TRAIL_STEPS = 200; | |
const float DT = 0.05; | |
const int SHADOW_STEPS = 32; | |
const float SHADOW_LEN = 0.3; | |
const float SMOOTHNESS = 0.7; | |
/* Posição da esfera com movimento complexo */ | |
vec2 spherePos(float t){ | |
float x = 0.5 + 0.35*sin(t*0.63 + sin(t*0.21)); | |
float y = 0.5 + 0.35*cos(t*0.41 + cos(t*0.17)); | |
return vec2(x, y); | |
} | |
/* Altura procedural com microdetalhes */ | |
float baseHeight(vec2 st){ | |
float h = 0.0; | |
float amp = 0.5; | |
vec2 q = st * 12.0; | |
for(int i=0;i<6;i++){ | |
h += fbm(q) * amp; | |
q *= 2.1; | |
amp *= 0.45; | |
} | |
return h; | |
} | |
/* Perfil do sulco com detalhes */ | |
float trenchAndRidge(float d){ | |
float r = RADIUS * 1.5; | |
float x = clamp(d / r, 0.0, 1.0); | |
float trench = (1.0 - x*x) * (1.0 - x) * TRENCH_DEPTH; | |
float ridge = exp(-pow((d - RADIUS)*3.5 / RADIUS, 2.0)) * (TRENCH_DEPTH * RIDGE_RATIO); | |
return ridge - trench; | |
} | |
/* Deslocamento com memória */ | |
float pathDisp(vec2 st){ | |
float minD = 1e5; | |
for(int i=0;i<TRAIL_STEPS;i++){ | |
float ti = u_time - float(i)*DT; | |
if(ti < 0.0) break; | |
vec2 p = spherePos(ti); | |
float d = length(st - p); | |
minD = min(minD, d); | |
} | |
return trenchAndRidge(minD); | |
} | |
/* Campo de altura com detalhes microscópicos */ | |
float heightField(vec2 st){ | |
float base = baseHeight(st); | |
// Detalhes microscópicos | |
float micro = 0.0; | |
for(int i=0; i<4; i++) { | |
micro += worley(st * pow(2.0, float(i)+5.0)) * pow(0.5, float(i)); | |
} | |
micro *= 0.04; | |
return base + pathDisp(st) + micro; | |
} | |
/* Normais com anisotropia */ | |
vec3 sandNormal(vec2 st){ | |
vec2 e = vec2(1.0) / u_resolution; | |
float hL = heightField(st - vec2(e.x, 0.)); | |
float hR = heightField(st + vec2(e.x, 0.)); | |
float hD = heightField(st - vec2(0., e.y)); | |
float hU = heightField(st + vec2(0., e.y)); | |
vec3 N = normalize(vec3(hL - hR, hD - hU, 2.0)); | |
// Rugosidade anisotrópica | |
float angle = sin(u_time * 0.5 + st.x * 10.0); | |
float bump = worley(st*40.0)*0.03 * angle; | |
float bL = worley((st-vec2(e.x,0.))*40.0)*0.03 * angle; | |
float bR = worley((st+vec2(e.x,0.))*40.0)*0.03 * angle; | |
float bD = worley((st-vec2(0.,e.y))*40.0)*0.03 * angle; | |
float bU = worley((st+vec2(0.,e.y))*40.0)*0.03 * angle; | |
vec3 N2 = normalize(vec3(bL - bR, bD - bU, 2.0)); | |
return normalize(mix(N, N2, 0.6)); | |
} | |
/* Cor da areia com variação física */ | |
vec3 sandColor(float h){ | |
vec3 dry = mix( | |
vec3(0.92,0.84,0.66), | |
vec3(0.85,0.77,0.60), | |
smoothstep(0.0, 1.0, sin(u_time * 0.1 + uv.x * 10.0)) | |
); | |
vec3 damp = mix( | |
vec3(0.65,0.57,0.45), | |
vec3(0.58,0.50,0.38), | |
smoothstep(0.0, 1.0, cos(u_time * 0.1 + uv.y * 10.0)) | |
); | |
float t = smoothstep(0.0,1.5,h); | |
vec3 base = mix(dry,damp,t); | |
// Grãos de areia | |
float grain = worley(uv*20.0 + sin(u_time * 0.2)) * 0.2; | |
base *= 1.0 + grain*0.15; | |
// Umidade realista | |
float moisture = smoothstep(0.5, -0.5, h); | |
base = mix(base, vec3(0.3,0.25,0.2), moisture * 0.4); | |
return base; | |
} | |
/* Sombras volumétricas */ | |
float volumetricShadow(vec2 st, vec3 L) { | |
float stepLen = SHADOW_LEN / float(SHADOW_STEPS); | |
vec2 dUV = L.xy / L.z * stepLen; | |
float density = 0.0; | |
float currentH = heightField(st); | |
for(int i=1; i<=SHADOW_STEPS; i++) { | |
vec2 ss = st + dUV * float(i); | |
float h = heightField(ss); | |
float proj = currentH + L.z * float(i) * stepLen; | |
if(h > proj) { | |
float diff = (h - proj) * 2.0; | |
density += exp(-diff*diff*8.0) * 0.05; | |
} | |
} | |
return exp(-density * 8.0); | |
} | |
/* Reflexão dinâmica */ | |
vec3 dynamicEnvReflection(vec2 st, vec3 N) { | |
vec3 ref = reflect(-vec3(0,0,1), N); | |
vec2 offset = ref.xy * 0.5 + 0.5; | |
// Parallax mapping fake | |
vec2 parallax = N.xy * 0.05; | |
vec3 layer1 = sandColor(baseHeight(offset * 1.0 + parallax)); | |
vec3 layer2 = sandColor(baseHeight(offset * 0.7 + parallax*0.7)); | |
vec3 layer3 = sandColor(baseHeight(offset * 0.4 + parallax*0.4)); | |
return mix(layer1, mix(layer2, layer3, 0.5), 0.4); | |
} | |
/* Subsurface scattering */ | |
vec3 subsurfaceScatter(vec2 st, vec3 N, vec3 L) { | |
float curvature = length(fwidth(N)) * 5.0; | |
float scatter = exp(-pow(abs(dot(L, N)), 1.5) * 8.0); | |
return mix(vec3(0.8,0.6,0.5), vec3(1.0), scatter) * curvature * 0.4; | |
} | |
/* Material PBR */ | |
struct Material { | |
vec3 albedo; | |
float metallic; | |
float roughness; | |
float ao; | |
}; | |
Material getMaterial(float h) { | |
Material m; | |
m.albedo = sandColor(h); | |
m.metallic = 0.0; | |
m.roughness = 0.65 + h * 0.25; | |
m.ao = clamp(1.0 + h*0.45, 0.2, 1.0); | |
return m; | |
} | |
/* Esfera refletora com detalhes */ | |
vec3 mirrorShade(vec2 st){ | |
vec3 V = vec3(0.0,0.0,1.0); | |
vec2 c = spherePos(u_time); | |
float z = sqrt(max(0.0, RADIUS*RADIUS - dot(st-c, st-c))); | |
vec3 N = normalize(vec3(st-c, z)); | |
vec3 R = reflect(-V,N); | |
// Reflexão dinâmica | |
vec3 env = dynamicEnvReflection(R.xy/R.z, N); | |
// Componentes de iluminação | |
vec3 L = normalize(vec3(0.2,0.6,1.0)); | |
float diff = max(dot(N,L),0.0); | |
float spec = pow(max(dot(reflect(-L,N),V),0.0),64.0); | |
float fres = pow(1.0 - max(dot(V,N),0.0),5.0); | |
// Subsurface scattering na esfera | |
vec3 sss = subsurfaceScatter(st, N, L) * 0.3; | |
return env*0.4 + env*0.6*fres + vec3(spec) + sss; | |
} | |
void main(){ | |
vec2 c = spherePos(u_time); | |
float h = heightField(uv); | |
vec3 N = sandNormal(uv); | |
vec3 L = normalize(vec3(0.45,0.45,1.0)); | |
float NdotL = max(dot(N,L), 0.0); | |
// Material PBR | |
Material mat = getMaterial(h); | |
// BRDF aproximado | |
vec3 H = normalize(L + vec3(0,0,1)); | |
float NdotH = max(dot(N, H), 0.0); | |
float roughness = mat.roughness; | |
float spec = pow(NdotH, 1.0 / max(roughness, 0.1)); | |
spec *= sqrt(1.0 - roughness); | |
// Sombras | |
float sh = volumetricShadow(uv, L); | |
// Subsurface scattering | |
vec3 sss = subsurfaceScatter(uv, N, L); | |
// Componentes de iluminação | |
vec3 diffuse = mat.albedo * NdotL * sh * 0.8; | |
vec3 specular = vec3(spec) * sh * 0.6; | |
// Reflexões | |
vec3 reflection = dynamicEnvReflection(uv, N) * 0.3; | |
// Cor base | |
vec3 color = diffuse + specular + sss + reflection; | |
// Oclusão ambiente | |
color *= mat.ao; | |
// LED de borda | |
float edge = min(min(uv.x,1.0-uv.x),min(uv.y,1.0-uv.y)); | |
color += vec3(1.0,0.92,0.70)*edge*0.65; | |
// Mistura com esfera | |
float inside = step(length(uv-c), RADIUS); | |
color = mix(color, mirrorShade(uv), inside); | |
// Efeitos finais | |
color *= 1.0 + 0.05*sin(u_time * 2.0 + uv.x * 50.0); // Brilho dinâmico | |
color = mix(color, vec3(0.95,0.9,0.85), 0.05*edge); // Borda suave | |
out_color = vec4(color,1.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment