Saltar al contenido

OpenGL: ¿Cómo renderizar un degradado rectangular perfecto?

Contamos con la contestación a esta obstáculo, al menos eso creemos. Si presentas inquietudes dínoslo, que sin pensarlo

Solución:

De hecho, el tipo de gradiente que desea se basa en 4 colores en cada píxel, donde OpenGL generalmente solo interpola la entrada sobre triángulos (por lo tanto, 3 entradas). Obtener el gradiente perfecto no es posible solo con los interpoladores estándar.

Ahora, como mencionaste, una textura 2×2 puede hacerlo. Si vio problemas de precisión, sugiero cambiar el formato de la textura a algo que normalmente requiera más precisión (como una textura flotante).

Por último, y como mencionaste también en tu pregunta, puedes resolver esto con un sombreador. Di que pasas un extra attribute por vértice que corresponde a (u,v) = (0,0) (0,1) (1,0) (1,0) hasta el sombreador de píxeles (con el sombreador de vértices simplemente pasando ).

Puede hacer lo siguiente en el sombreador de píxeles (nota, la idea aquí es sólida, pero no probé el código):

Fragmento de sombreador de vértices:

varying vec2 uv;
attribute vec2 uvIn;

uv = uvIn;

Sombreador de fragmentos:

uniform vec3 color0;
uniform vec3 color1;
varying vec2 uv;

// from wikipedia on bilinear interpolation on unit square:
// f(x,y) = f(0,0)(1-x)(1-y) + f(1,0)x(1-y) + f(0,1)(1-x)y + f(1,1) xy. 
// applied here:
// gl_FragColor = color0 * ((1-x)*(1-y) + x*y) + color1*(x*(1-y) + (1-x)*y)
// gl_FragColor = color0 * (1 - x - y + 2 * x * y) + color1 * (x + y - 2 * x * y)
// after simplification:
// float temp = (x + y - 2 * x * y);
// gl_FragColor = color0 * (1-temp) + color1 * temp;
gl_FragColor = mix(color0, color1, uv.u + uv.v - 2 * uv.u * uv.v);

El problema es porque usas un quad. El quad se dibuja usando dos triángulos, pero los triángulos no están en la orientación que necesitas.

Si defino los vértices cuádruples como:

  • A: vértice inferior izquierdo
  • B: vértice inferior derecho
  • C: vértice superior derecho
  • D: vértice superior izquierdo

Diría que el quad está compuesto por los siguientes triángulos:

  • ABD
  • DBC

Los colores asignados a cada vértice son:

  • A: amarillo
  • B: rojo
  • C: amarillo
  • D: rojo

Teniendo en cuenta la geometría (los dos triángulos), los píxeles entre D y B son resultado de la interpolación entre rojo y rojo: ¡en efecto, rojo!

La solución sería una geometría con dos triángulos, pero orientados de forma diferente:

  • A B C
  • DCA

Pero probablemente no obtendrá el gradiente exacto, ya que en medio del cuadrante obtendrá un amarillo completo, en lugar de un amarillo. mixed con rojo. Entonces, supongo que puedes lograr el resultado exacto usando 4 triángulos (o un abanico de triángulos), en los que el vértice centrado es la interpolación entre el amarillo y el rojo.


¡Guau! Efectivamente el resultado no es el que esperaba. Pensé que el gradiente se producía por interpolación lineal entre colores, pero seguramente no lo es (¡realmente necesito configurar el espacio de color de la pantalla LCD!). De hecho, la solución más escalable es la renderización mediante sombreadores de fragmentos.

Mantener la solución propuesta por Bahbar. Aconsejaría comenzar la implementación de un sombreador de vértices/fragmentos de paso (especificando solo vértices y colores, debe obtener el resultado anterior); entonces, empieza a jugar con el mezcla y la coordenada de la textura pasada al sombreador de vértices.

Realmente necesita comprender la canalización de renderizado con sombreadores programables: vertex shader se llama una vez por vértice, fragment shader se llama una vez por fragmento (sin multimuestreo, un fragmento es un píxel; con multimuestreo, un píxel está compuesto por muchos fragmentos que se interpolan para obtener el color del píxel).

El vertex shader toma los parámetros de entrada (uniformes y entradas; los uniformes son constantes para todos los vértices emitidos entre glBegin/glEnd; las entradas son características de cada instancia de vertex shader (4 vértices, 4 instancias de vertex shader).

Un sombreador de fragmentos toma como entrada las salidas del sombreador de vértices que ha producido el fragmento (debido a la rasterización de triángulos, líneas y puntos). En el Bahbar respuesta la única salida es el ultravioleta variable (común a ambas fuentes de sombreado).

En su caso, el sombreador de vértices genera las coordenadas de textura de vértice UV (pasadas “tal cual”). Estas coordenadas UV están disponibles para cada fragmento y se calculan interpolando los valores generados por el sombreador de vértices según la posición del fragmento.

Una vez que tengas esas coordenadas, solo necesitas dos colores: el rojo y el amarillo en tu caso (en Bahbar respuesta corresponde a color0 y color1 uniformes). Luego, mezcle esos colores según las coordenadas UV del fragmento específico.

Aquí está el poder de los sombreadores: puede especificar diferentes métodos de interpolación simplemente modificando la fuente del sombreador. La interpolación lineal, bilineal o spline se implementa especificando uniformes adicionales al sombreador de fragmentos.¡Buena práctica!

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *