» Tutorial Effects - Manipular Colores
This site relies heavily on Javascript. You should enable it if you want the full experience. Learn more.

Tutorial Effects - Manipular Colores

English | Italian | Mandarin | Japanese

TOC: Of Effects and Shaders
Back: Pixelshader Preparations
Next: Texture Coordinates


El código en el que debemos concentrarnos ahora es la función PixelShader:

  1. float4 PS(vs2ps In): COLOR
  2. {
  3.     return 1;
  4. }

Piensa que esta función está llamando a cada uno de los pixel de la malla que aparecen en la pantalla (screenspace).

float4 = color of a pixel

Como ves la función tiene un float4 de tipo devolver (return). PS es el nombre de la función, podría ser cualquier otro realmente, sólo tiene que corresponder a su mención en la técnica de bloque en la parte inferior del archivo.

El float4 dice que la función tiene que devolver un vector con 4 componentes que forman el color de un píxel. Los 4 componentes son, en este orden particular:

  • rojo
  • verde
  • azul
  • alpha

Por tanto, si en vez de 1 devolvemos un float4 como

return float4(1, 0, 0, 1);

tu quad se verá completamente rojo ya que el rango de cada componente va del 0 al 1 (no del 0 al 255).

En vez de devolver el float4 directamente como arriba puedes definir una variable de tipo float4 primero, hacer algo con ella y después devolver la variable:

float4 col;
col = float4(1, 0, 0, 1);
col /= 2;     //sintaxis corta para: col = col / 2
return col;

Resulta un rojo más oscuro ya que la variable col muestra los siguientes valores después de dividirla entre 2:

 (0.5, 0, 0, 0.5)

Como ves las operaciones matemáticas en el float4 (como dividir entre 2) son aplicadas a todos los componentes del vector a la vez.

Acceder a componentes/canales individuales del color

También puedes operar individualmente en cada uno de los componentes:

float4 col = float4(1, 0, 0, 1);
col.g = col.r / 2;
return col;

que devuelve el siguiente output:

 (1, 0.5, 0, 1)

Por medio del denominado swizzling puedes acceder a los componente individuales de un vector. Los swizzles básicos son .r, .g, .b, y .a para los cuatro componentes del color, pero puedes usarlos en otras combinaciones arbitrarias como:

 col = col.bgra;

que reordenarán los componentes de color de la variable resultando:

 (0, 0.5, 1, 1)

Really all combinations are allowed with swizzling, even things like:
.rrgg
.rb
.abba
...te haces una idea....

Mostrar una textura

En el pin Filename de FileTexture (EX9.Texture)elige un archivo de imagen a tu gusto.
Para acceder a una textura en el pixelshader y devolver el color de uno de sus pixel es necesaria esta línea de código:

return tex2D(Samp, In.TexCd);

Here we directly return the result of the function tex2D (which is a float4) as the pixels color. The function takes a sampler as its first parameter and a texture coordinate as its second input.

Haciendo dobleclick sobre cualquier palabra en el editor de código marca todas las apariciones de esa palabra, así si lo haces en la sampler variable Samp verás que está definida al comienzo del archivo. Un sampler es una estructura que combina una textura y alguno estados de sampler (sampler states). Vamos a dejar las cosas así por el momento y ya nos preocuparemos de las coordenadas de textura más tarde.

Ahora vamos a jugar un poco con los canales de color de la textura:

float4 col = tex2D(Samp, In.TexCd);
return col.bgra;

Aquí estamos sampleando el color de una imagen asignándole la variable que hemos llamado col. En lugar de devolver col como los pixel de color actuales, estamos cambiando los canales de color rojo y azul para devolver eso.
float4 col = tex2D(Samp, In.TexCd);

float4 col = tex2D(Samp, In.TexCd);
return col.b;  //sintaxis corta para: return float4(col.b, col.b, col.b, col.b)

o podemos también ver solo el componente azul de la imagen aplicado al conjunto de los 4 canales.

Invertir una textura

Para invertir una textura queremos invertir solo los canales rojo, verde y azul, pero dejar el canal alpha como está:

float4 col = tex2D(Samp, In.TexCd);
col.rgb = 1 - col.rgb;
return col;

Contrastar una textura

El contraste de una imagen puede ser incrementado aumentando los valores de todos los canales por encima de 0.5 o disminuyendolo por debajo de 0.5. Para hacer esto, primero movemos el rango de valores por dejajo de 0.5 para poder realizar un escalado simétrico en ambas direcciones (alrededor de 0) por medio de la multiplicación con el Contrasting factor. Entonces elevamos el rango otra vez entre 0 y 1.

float4 col = tex2D(Samp, In.TexCd);
col.rgb -= 0.5;
col.rgb *= Contrast;
col.rgb += 0.5;
return col;

Al guardarlo nos da un error:

 undeclared identifier 'Contrast'

porque todavía no hemos definido “Contrast”. Así que justo encima de la función PixelShader escribe:

 float Contrast = 1;

para definir una variable llamada Contrast e inicializarla con el valor 1. Guarda. Observa que automáticamente ha aparecido un nuevo pin llamado Contrast en el nodo effect. Cambiando el valor de este pin cambiarás el contraste de la imagen.

Convertir a escala de grises

Como nos cuenta the internet hay una fórmula simple para convertir una imagen en su correpondiente escala de grises recogiendo la luminosidad precibible de cada uno de sus tres canales de color en una cuenta. La idea consiste en sumar el 30% del valor del rojo, el 59% del valor del verde, y el 11% del valor del azul. Esto se puede hacer de dos formas diferentes:

float4 col = tex2D(Samp, In.TexCd);
col.rgb = col.r * 0.3 + col.g * 0.59 + col.b * 0.11;
return col;

Una manera más elgante de usar dot product entre dos vectores:

const float3 lumCoeff = {0.3, 0.59, 0.11};
col.rgb = dot(col.rgb, lumCoeff);

Que hace exactamente lo mismo que las líneas de arriba.

Reutilizar el código en funciones

Imagina que queremos usar la conversión a escala de grises más de una vez en nuestro código. En lugar de escribir el código más veces, podemos separarlo en una función para poder reutilizarlo. Para ello creamos una nueva función llamada ConvertToGray que devuelve un float4 y recoge un float4 como parámetro:

float4 ConvertToGray(float4 col)
{
    const float4 lumcoeff = {0.3, 0.59, 0.11, 0};
    return dot(col, lumcoeff);
}

Podemos usar esta función en la función Pixelshader principal de este modo:

float4 col = tex2D(Samp, In.TexCd);
return ConvertToGray(col);

Voila. Ahora ajusten sus cinturones!!!


Next: Texture Coordinates
Back: Pixelshader Preparations
TOC: Of Effects and Shaders

anonymous user login

Shoutbox

~16h ago

metrowave: @mediadog, YOU lucky dog!

~20h ago

~1d ago

colorsound: Hi guys some poc of laser and projection ;D https://vimeo.com/colorsound/laser-projection-interaction

~2d ago

mediadog: @metrowave I just saw the Wilfred Lumia exhibit in DC - I wept. Pics/videos do it no justice, analog = infinite resolution!

~4d ago

udo2013: BeatDetector(bass)not working.ErrorCode from red node:"PLUGINS \BassSound dll BassSound Data BeatDetectorNode" is missing.WhatToDo?