1 export const vertexShader = ` 2 precision highp float; 3 4 // Atributos de los vértices 5 attribute vec3 position; // Posición del vértice 6 attribute vec3 normal; // Normal del vértice 7 attribute vec2 uv; // Coordenadas de textura 8 9 // Uniforms 10 uniform mat4 modelMatrix; // Matriz de transformación del objeto 11 uniform mat4 viewMatrix; // Matriz de transformación de la cámara 12 uniform mat4 projectionMatrix; // Matriz de proyección de la cámara 13 uniform mat4 worldNormalMatrix; // Matriz de normales 14 15 // Varying 16 varying vec2 vUv; // Coordenadas de textura que se pasan al fragment shader 17 varying vec3 vNormal; // Normal del vértice que se pasa al fragment shader 18 varying vec3 vWorldPos; // Posición del vértice en el espacio de mundo 19 20 void main() { 21 // Lee la posición del vértice desde los atributos 22 vec3 pos = position; 23 24 // Se calcula la posición final del vértice 25 // Se aplica la transformación del objeto, la de la cámara y la de proyección 26 gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(pos, 1.0); 27 28 // Se pasan las coordenadas de textura al fragment shader 29 vUv = uv; 30 vNormal = normalize(vec3(worldNormalMatrix * vec4(normal, 0.0))); 31 vWorldPos = (modelMatrix * vec4(pos, 1.0)).xyz; 32 } 33 `; 34 35 export const fragmentShader = ` 36 precision mediump float; 37 varying vec2 vUv; 38 varying vec3 vNormal; 39 varying vec3 vWorldPos; 40 41 uniform float scale; 42 uniform float terrainAmplitude; 43 uniform float terrainAmplitudeBottom; 44 uniform float dirtStepWidth; 45 uniform float rockStepWidth; 46 47 uniform sampler2D dirtSampler; 48 uniform sampler2D rockSampler; 49 uniform sampler2D grassSampler; 50 51 float normalize(float inputValue, float minValue, float maxValue) { 52 return (inputValue - minValue) / (maxValue - minValue); 53 } 54 55 void main(void) { 56 vec2 uv = vUv*8.0; 57 vec2 uv2 = vUv*scale; 58 59 float heightFactor = vWorldPos.y - terrainAmplitudeBottom; 60 float heightFactorNormalized = normalize(heightFactor, 0.0, terrainAmplitude); 61 62 vec3 grass = texture2D(grassSampler, uv).xyz; 63 vec3 dirt = texture2D(dirtSampler, uv*4.0).xyz; 64 vec3 rock = texture2D(rockSampler, uv).xyz; 65 66 // muestreo de pasto a diferentes escalas, luego se combina con \`mix()\` 67 vec3 grass1 = texture2D(grassSampler, uv2*1.00).xyz; 68 vec3 grass2 = texture2D(grassSampler, uv2*3.13).xyz; 69 vec3 grass3 = texture2D(grassSampler, uv2*2.37).xyz; 70 vec3 colorGrass = mix(mix(grass1,grass2,0.5),grass3,0.3); 71 72 // lo mismo para la textura de tierra 73 vec3 dirt1 = texture2D(dirtSampler, uv2*3.77).xyz; 74 vec3 dirt2 = texture2D(dirtSampler, uv2*1.58).xyz; 75 vec3 dirt3 = texture2D(dirtSampler, uv2*1.00).xyz; 76 vec3 colorDirt = mix(mix(dirt1, dirt2, 0.5), dirt3, 0.3); 77 78 // lo mismo para la textura de roca 79 vec3 rock1 = texture2D(rockSampler,uv2*0.40).xyz; 80 vec3 rock2 = texture2D(rockSampler,uv2*2.38).xyz; 81 vec3 rock3 = texture2D(rockSampler,uv2*3.08).xyz; 82 vec3 colorRock = mix(mix(rock1, rock2, 0.5), rock3,0.5); 83 84 float u = heightFactorNormalized; 85 86 // float pi = 3.141592654; 87 // float grassFactor = sin(pi*u); 88 // float dirtFactor = abs(sin(2.0*pi)); 89 // float rockFactor = clamp(cos(2.0*pi*u), 0.0, 1.0); 90 91 float width2 = rockStepWidth; 92 float rockFactor = 2.00 - smoothstep(0.0, width2, u) 93 - smoothstep(1.0, 1.00 - width2, u); 94 95 float width = dirtStepWidth; 96 float s1 = smoothstep(0.00, width, u); 97 float s2 = smoothstep(width, width*2.0, u); 98 float s3 = smoothstep(0.50, 0.50 + width, u); 99 float s4 = smoothstep(0.50 + width, 0.50 + width*2.0, u); 100 float dirtFactor = (s1 - s2) + (s3 - s4); 101 102 float grassFactor = smoothstep(0.0, 0.35, u) - smoothstep(0.35, 1.00, u); 103 104 vec3 colorDirtGrass = mix(colorDirt, colorGrass, grassFactor); 105 vec3 colorDirtGrassDirt = mix(colorDirtGrass, colorDirt, dirtFactor); 106 vec3 color = mix(colorDirtGrassDirt, colorRock, rockFactor); 107 108 gl_FragColor = vec4(color, 1.0); 109 }`;