Funciones de modelado

Starter pack

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 color
  • uTime: el tiempo transcurrido desde el comienzo de la aplicaci贸n
  • vUv: 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煤mero x y te da x * 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

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 umbral
  • x: 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.

Representaci贸n de la funci贸n Step

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);
}

Representaci贸n vertical de la funci贸n Step

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);
}

Representaci贸n revertida de la funci贸n Step

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 valor
  • y: el segundo valor
  • a: el valor a interpolar entre x y y

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);
}

Mix function representation

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);
}

Mix function two colors

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);
}

Mix function two colors with pct

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.

Graphtoy mix function

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 inferior
  • edge1: el borde superior
  • x: el valor a interpolar entre edge0 y edge1

Devuelve tres resultados diferentes:

  • 0.0 si x es menor que edge0
  • 1.0 si x es mayor que edge1
  • una interpolaci贸n suave entre 0.0 y 1.0 si x est谩 entre edge0 y edge1

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);
}

Smoothstep function representation

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);
}

Min & Max function representation

Los colores est谩n deslavados y la transici贸n es muy suave.

Vamos a visualizarlo en Graphtoy:

Max graph

Representaci贸n de max(x, 0.4)

Min graph

Representaci贸n de min(x, 0.6)

Y si los combinamos:

Min & Max graph

Puedes ver que nuestros valores nunca bajan de 0.4 y nunca suben de 0.6.

Nuestra combinaci贸n de las funciones min y max puede ser reemplazada por la funci贸n clamp, que es una abreviatura de min(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.