• Braulio Madrid

Tutorial Shaders - Haciendo un Cubo RGB

Actualizado: may 27

Este tutorial discute los parámetros de salida de vértice y los parámetros de entrada fragmento. mencionado en el blog anterior "Shader Minimalista".


En este blog haremos un shader para cubo #RGB  muy chulo ya lo veréis. El color de cada punto de la superficie está determinada por sus coordenadas; es decir, un punto en la posición (x,y,z) tiene el color (rojo,verde,azul) = (x,y,z). Por ejemplo (x,y,z) = (0,0,1), el punto se asigna al color(rojo,verde,azul) = (0,0,1), es decir, azul puro.


Dado que queremos crear un cubo RGB, crearemos un cubo desde la jerarquía, puede crear un objeto de juego con el cubo seleccionando GameObject> Crear Otros> Cubo en el menú principal. Continuar con la creación de un material y un objeto Shader y de fijar el shader para el material y el material al cubo. 

Shader "Cg shader for RGB cube" { 
   SubShader { 
      Pass { 
         CGPROGRAM 
 
         #pragma vertex vert // programa de vertices
         #pragma fragment frag // programa de fragmentos
 
         // una estructura definida para la salida de vertice
         struct vertexOutput {
            float4 pos : SV_POSITION; //System value position
            float4 col : TEXCOORD0;
         };
         //// vertex shader
         vertexOutput vert(float4 vertexPos : POSITION) {
            vertexOutput output; // declaramos como retorno la estructura de arriba
 
            output.pos =  mul(UNITY_MATRIX_MVP, vertexPos);
            output.col = vertexPos + float4(0.5, 0.5, 0.5, 0.0);
               // Aqui escribimos la salida de la estructura
               // coloreamos los vertices con la posicion 
               // de las coordenadas x, y, z, Sumamos 0.5 porque
               // el cubo o la esfera estan entre -0.5 a 0.5
               // pero necesitamos un valor entre 0 y 1
            return output;
         }
 
         float4 frag(vertexOutput input) : COLOR // fragment shader
         {
            return input.col; 
               // Aqui usamos la salida del vertex shader y retornamos el
               // color
         }
 
         ENDCG  
      }
   }
}

Si el cubo no es de color correctamente, compruebe la consola para los mensajes de error (seleccionando Window > Console desde el menú principal), asegúrese de que ha guardado el código de shader, y comprobar si se ha conectado el objeto shader al objeto material y el objeto material al objeto juego.


La principal tarea de nuestro shader es establecer el color de salida fragmento (es decir, el parámetro de salida fragmento con semántica COLOR) en el fragment shader a la posición de vértice que está disponible en el vertex shader. En realidad, esto no es del todo cierto: las coordenadas en el parámetro de entrada vértice con semántica POSITION de cubo por defecto de la Unidad están entre -0,5 y 0,5, mientras que nos gustaría tener componentes de color entre 0.0 y 1.0; por lo tanto, tenemos que añadir 0,5 a la x, y, y el componente z, que se hace con esta expresión: vertexPos + float4 (0.5, 0.5, 0.5, 0.0).


El problema principal, sin embargo, es: ¿cómo hacemos para cualquier valor desde el vertex shader para el fragment shader? Resulta que la única manera de hacer esto es utilizar pares de parámetros de salida de vértice y los parámetros de entrada fragmento con la misma semántica (TEXCOORD0 en este caso). De hecho, es sólo la semántica que se utilizan para determinar qué vértice parámetros de salida corresponden a qué parámetros de entrada fragmento. En lugar de la TEXCOORD0 semántica también podríamos utilizar otra semántica, por ejemplo, COLOR, que en realidad no importa aquí, salvo que los parámetros con el color semántica menudo se sujetan a valores entre 0 y 1 (que puede estar bien en este caso). Es, sin embargo, común a utilizar la semántica TEXCOORD0, TEXCOORD1, TEXCOORD2, etc. para todo tipo de parámetros.


El siguiente problema es especificar varios parámetros de salida vértice. Puesto que la instrucción de retorno sólo puede devolver un valor, es común para definir una estructura para todos los parámetros de salida de vértices requeridos. Aquí, esta estructura se llama vertexOutput:

struct vertexOutput {
  fixed4 pos :SV_POSITION;
  fixed4 col :TEXCOORD0;
  };

Mediante el uso de esta estructura como un argumento de la función fragmento shader, nos aseguramos de que la semántica partido. Tenga en cuenta que en el Decimoquinto (en contraste con C), no tenemos que escribir struct vertexOutput la hora de definir las variables de este tipo, pero sólo podemos utilizar el nombre vertexOutput (sin estructura) para el mismo tipo.


Una alternativa al uso de una estructura de salida sería el uso de argumentos de la función de sombreado de vértice con el calificador a cabo, por ejemplo:

Shader "Cg shader for RGB cube" { 


Shader "Cg shader for RGB cube" { 
   SubShader { 
      Pass { 
         CGPROGRAM 
 
         #pragma vertex vert // vert function is the vertex shader 
         #pragma fragment frag // frag function is the fragment shader
 
         void vert(float4 vertexPos : POSITION,
            out float4 pos : SV_POSITION,
            out float4 col : TEXCOORD0)  
         {
            pos =  mul(UNITY_MATRIX_MVP, vertexPos);
            col = vertexPos + float4(0.5, 0.5, 0.5, 0.0);
            return;
         }
 
         float4 frag(float4 pos : SV_POSITION, 
            float4 col : TEXCOORD0) : COLOR 
         {
            return col; 
         }
 
         ENDCG 
      }
   }
}

Sin embargo, el uso de una estructura de salida es más común en la práctica y se asegura de que los parámetros de salida vértice y los parámetros de entrada de fragmentos tienen una semántica coincidentes.


Variaciones de este Shader

El cubo RGB representa el conjunto de colores disponibles (es decir, toda la gama de la pantalla). Por lo tanto, se puede utilizar también mostrar el efecto de una transformación de color. Por ejemplo, un color a gris transformación podría calcular la media de los componentes de color rojo, verde, y azul, es decir, y luego poner este valor en los tres componentes de color del color fragmento para obtener un valor de gris de la misma luminosidad. En lugar de la media, la luminancia relativa también podría ser utilizado, que es. Por supuesto, cualquier otra transformación de color (cambio de saturación, contraste, tono, etc.) es también aplicable.


Otra variación de este shader podría calcular un #CMY (cian, magenta, amarillo) cubo: para la posición que usted podría restar de un blanco puro de una cantidad de rojo que es proporcional a fin de producir cian. Además, debe restar una cantidad de verde en proporción al componente para producir magenta y también una cantidad de azul en proporción a producir amarillo.


Si usted realmente desea conseguir la suposición, se podía calcular un HSV (tono, saturación, valor) del cilindro. Por y coordina entre -0.5 y 0.5, puede obtener un ángulo entre 0 y 360 ° con 180,0 + grados (atan2 (z, x)) en el GC y una distancia entre 0 y 1 del eje con 2,0 * sqrt (x * x + z * z). La coordenada de la Unidad de cilindro incorporado está entre -1 y 1 que se puede traducir a un valor entre 0 y 1 por. El cálculo de los colores RGB de HSV coordenadas se describe en el artículo sobre #HSV en Wikipedia.


Interpolación de los parámetros Vertex Output

La historia acerca de los parámetros de salida del vértice y los parámetros de entrada fragmento no está del todo concluido todavía. Si selecciona el objeto juego de cubo, que se verá en la vista de escena que consta de sólo 12 triángulos y 8 vértices. Así, el vertex shader podría llamarse sólo ocho veces y sólo ocho salidas diferentes se escriben en los parámetros de salida vértice.


Por otra parte, hay muchos más colores en el cubo. ¿Cómo sucedió eso?.

De hecho, el vertex shader sólo se llama para cada vértice de cada triángulo.


Pero los diferentes valores de los parámetros de salida vértice para los diferentes vértices se interpolan a través del triángulo. El shader fragmento se denomina a continuación, para cada píxel que está cubierta por el triángulo y recibe valores de los parámetros de salida vértice como parámetros de entrada fragmento interpolada.


Si desea asegurarse de que un fragment shader recibe un valor exacto, no interpolada por un vertex shader, usted tiene que asegurarse de que el vertex shader escribe el mismo valor a los parámetros de salida vértice para todos los vértices de un triángulo.


© 2023 por Darkcom. Proudly created with Wix.com | Peñol, Antioquia, Colombia| +57 3113389725 | Politica de privacidad

  • GitHub
  • BMadrid
  • DarkcomDev
  • Darkcom.dev
  • Braulio-Madrid
  • YouTube Darkcom Tech
This site was designed with the
.com
website builder. Create your website today.
Start Now