鈿★笍 Limited Black Friday Deal
Get 50% off on the React Three Fiber Ultimate Course with the promo code ULTIMATE50
Buy Now
Fundamentals
Core
Master
Shaders
Funciones de modelado
La l贸gica del shader es especial, es diferente de lo que estamos acostumbrados en JavaScript u otros lenguajes de programaci贸n. Aunque la sintaxis es similar, la forma en que implementamos la l贸gica es distinta. Es un poco como una caja negra, pones algunos datos y obtienes algunos colores para el fragment shader, o algunas posiciones para el vertex shader.
Pero, 驴c贸mo se controla la salida? 驴C贸mo haces que se vea como quieres? Aqu铆 es donde entran las funciones de modelado.
Nos enfocaremos en el fragment shader para esta lecci贸n, pero los mismos principios se aplican al vertex shader.
Zona de pr谩ctica
Para dominar el arte del modelado, necesitar谩s practicar y experimentar. Te llevar谩 tiempo acostumbrarte a la forma en que funciona el shader, pero una vez que lo domines, podr谩s crear efectos incre铆bles.
Porque quiero ponerte en la mejor posici贸n para tener 茅xito, he preparado esta escena de Galer铆a de Arte 3D para que visualices tus shaders en tiempo real en un ambiente agradable.
驴Puedes sentir fluir tu creatividad? 隆Todos esos marcos vac铆os est谩n esperando tus obras maestras!
El modelo 3D usado es VR Gallery de Maxim Mavrichev y est谩 licenciado bajo Creative Commons Attribution.
Us茅 <CameraControls />
para crear una c谩mara en primera persona para navegar dentro de la galer铆a y Squoosh para reducir el tama帽o de las texturas.
SimpleShaderMaterial
Todos los marcos de la galer铆a son copias de SimpleShaderMaterial
, es un shader personalizado b谩sico que prepar茅 para ti con:
uColor
: un coloruTime
: el tiempo transcurrido desde el comienzo de la aplicaci贸nvUv
: las coordenadas UV del fragment (0 a 1 en ambos ejes)
Todos se extienden en el <App.jsx />
para poder usarlos de forma declarativa en nuestra escena.
Se nombran en funci贸n de su posici贸n en la galer铆a, pero si茅ntete libre de renombrarlos a algo m谩s significativo una vez que hayas creado obras maestras con ellos.
Funciones
Para cada fragmento de nuestro shader, nuestro mismo c贸digo se ejecutar谩 con diferentes entradas.
Si queremos dibujar una l铆nea, podr铆amos usar if statements para verificar si el p铆xel est谩 dentro de la l铆nea o no. Pero hacer formas m谩s complejas ser铆a muy dif铆cil e ineficiente.
En su lugar, usamos funciones para dar forma a nuestra salida. No te preocupes, no necesitas ser un experto en matem谩ticas para usarlas. Solo necesitas entender qu茅 funciones est谩n a tu disposici贸n y qu茅 hacen.
Piensa en una funci贸n como una m谩quina que toma una entrada y te da una salida. Por ejemplo, la funci贸n
f(x) = x * 2
toma un n煤merox
y te dax * 2
como resultado.
Para visualizar el efecto de las diferentes funciones, utilizaremos Graphtoy, es una herramienta simple para escribir funciones y ver su salida. Ayuda a validar nuestra comprensi贸n de las funciones cuando experimentamos con ellas en nuestros shaders.
Vamos a visualizar nuestra funci贸n f(x) = x * 2
en Graphtoy:
Graphtoy se convertir谩 r谩pidamente en tu mejor amigo cuando experimentes con shaders.
Es hora de experimentar con las diferentes funciones a nuestra disposici贸n.
Step
La funci贸n step es una funci贸n simple que devuelve 0
si la entrada es menor que un umbral, y 1
si la entrada es mayor que el umbral.
Toma dos par谩metros:
edge
: el umbralx
: el valor de entrada
Vamos a probarlo en el fragment shader del frame frontal ArtFront02Material.jsx
:
void main() { float pct = 1.0; pct = step(0.5, vUv.x); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
Declaramos una variable pct
para determinar el porcentaje del color que queremos mostrar. La configuramos a 1.0
por defecto, y luego usamos la funci贸n step
para configurarla a 0.0
si el vUv.x
es menor que 0.5
.
Podemos ver que la mitad izquierda del frame es negra, y la mitad derecha tiene el color establecido en el uniforme uColor
.
Vamos a aplicarlo al eje vertical con un umbral diferente:
void main() { float pct = 1.0; pct = step(0.2, vUv.y); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
Podemos ver que el 20% de la parte inferior del frame es negra, y el resto es p煤rpura.
Las coordenadas UV tienen el origen en la esquina inferior izquierda del frame, por lo que
[0, 0]
es la esquina inferior izquierda, y[1, 1]
es la esquina superior derecha.
Si quieres revertir el efecto, simplemente puedes intercambiar los par谩metros de la funci贸n step
:
void main() { float pct = 1.0; pct = step(vUv.y, 0.2); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
Ahora tenemos el efecto opuesto.
Mix
La funci贸n mix es una funci贸n simple que devuelve una interpolaci贸n lineal entre dos valores.
Toma tres par谩metros:
x
: el primer valory
: el segundo valora
: el valor a interpolar entrex
yy
Vamos a probarlo:
void main() { float pct = 1.0; pct = mix(0.0, 1.0, vUv.x); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
Podemos ver un bonito degradado de negro a p煤rpura.
Como muchas otras funciones, puedes usarla en otros tipos de datos, como los componentes vectoriales. Vamos a usarla para crear un degradado de blanco a p煤rpura en el eje vertical:
void main() { vec3 whiteColor = vec3(1.0); vec3 finalColor = mix(whiteColor, uColor, vUv.y); gl_FragColor = vec4(finalColor, 1.0); }
Podemos ver un bonito degradado de blanco a p煤rpura.
Vamos a cambiar el valor de interpolaci贸n llamando a la funci贸n mix
una primera vez para obtener el valor pct
, y luego usarlo para interpolar entre el whiteColor
y el uColor
:
void main() { vec3 whiteColor = vec3(1.0); float pct = mix(0.0, 0.3, vUv.y); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
El p煤rpura es muy claro ya que el valor m谩ximo de pct
es 0.3
.
Utiliza Graphtoy para experimentar con la funci贸n mix
y entender c贸mo funciona.
3 interpolaciones diferentes con la funci贸n mix
dan resultados completamente diferentes.
Smoothstep
La funci贸n smoothstep es una funci贸n simple que devuelve una interpolaci贸n suave entre dos valores.
Toma tres par谩metros:
edge0
: el borde inferioredge1
: el borde superiorx
: el valor a interpolar entreedge0
yedge1
Devuelve tres resultados diferentes:
0.0
six
es menor queedge0
1.0
six
es mayor queedge1
- una interpolaci贸n suave entre
0.0
y1.0
six
est谩 entreedge0
yedge1
Vamos a usarlo para cambiar nuestro valor pct
:
void main() { vec3 whiteColor = vec3(1.0); float pct = smoothstep(0.4, 0.6, vUv.y); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
La transici贸n ahora es solo entre 0.4
y 0.6
. Todo lo que est谩 por debajo es blanco, y todo lo que est谩 por encima es p煤rpura.
Min & Max
min
y max
son funciones simples que devuelven el valor m铆nimo o m谩ximo entre dos entradas. Funcionan exactamente como las funciones Math.min
y Math.max
en JavaScript.
Vamos a usarlas para ajustar nuestro valor pct
. Primero vamos a asegurarnos de que nunca sea inferior a 0.4
(lo que significa que nunca ser谩 totalmente blanco):
void main() { vec3 whiteColor = vec3(1.0); float pct = smoothstep(0.4, 0.6, vUv.y); pct = max(pct, 0.4); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
Y nunca superior a 0.6
(lo que significa que nunca ser谩 totalmente p煤rpura):
void main() { vec3 whiteColor = vec3(1.0); float pct = smoothstep(0.4, 0.6, vUv.y); pct = max(pct, 0.4); pct = min(pct, 0.6); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
Los colores est谩n deslavados y la transici贸n es muy suave.
Vamos a visualizarlo en Graphtoy:
Representaci贸n de max(x, 0.4)
Representaci贸n de min(x, 0.6)
Y si los combinamos:
Puedes ver que nuestros valores nunca bajan de 0.4
y nunca suben de 0.6
.
Nuestra combinaci贸n de las funciones
min
ymax
puede ser reemplazada por la funci贸n clamp, que es una abreviatura demin(max(x, min), max)
.
Operaciones y patrones
Antes de descubrir muchas otras funciones 煤tiles, veamos c贸mo podemos usar operaciones para crear patrones.
End of lesson preview
To get access to the entire lesson, you need to purchase the course.