HLSL, Un poco de historia

HLSL (High Level Shader Language) es el lenguaje desarrollado por Microsoft con el que podemos programar efectos gráficos mediante DirectX para que sean ejecutados por la GPU (Graphics Processor Unit) situada en nuestras actuales tarjetas gráficas, con el se pueden aplicar efectos gráficos tan impresionantes como:

Faces

Pero como se ha llegado hasta todo esto que hoy conocemos y nos es tan común, pues todo empezó en 1995 con la salida de la primera tarjeta aceleradora gráfica 3D para consumo doméstico lanzada por la en aquellos tiempos empresa llamada 3Dfx, estoy convencido que todos recordaréis los inicios y lo que suponía arrancar un juego con y sin que apareciese este logo al arrancar:

 

La 3Dfx Voodoo Card fue la primera por aquellos tiempos uno necesitaba una tarjeta gráfica 2D y una tarjeta aceleradora de gráficos 3D, finalmente esto se fue unificando en una sola tarjeta y las llamadas tarjetas aceleradoras pasaron a ser nuestras tarjetas gráficas 2D y 3D. Estas tarjetas provocaron una revolución en el mundo de los videojuegos aunque sus posibilidades eran muy limitadas, se empezó a pensar en trasladar gran parte del cálculo especifico en los videojuegos de la CPU hacia la GPU.

El próximo salto lo dio Nvidia con el lanzamiento de la GeForce 256 la cual liberaba a la CPU del cálculo de transformación e iluminación (Transform & Lighting) y permitía por tanto tener muchísimos más objetos en pantalla iluminados al realizar esta operación por hardware:

T&L

Hubo una segunda generación basada en esto introducida en el mercado por Nvidia a partir de su GeForce 2 y ATI con su gama Radeon, pero en aquellos entonces todas las capacidades gráficas estaba implementadas mediante fixed-functions, lo cual significaba que solo podías aplicar a los objetos las transformaciones e iluminación que permitía el hardware de la tarjeta gráfica, esto provocó que muchos juegos de la época tuviesen un aspecto muy parecido.

Cabe destacar también como 3Dfx lanzó con su tarjeta Voodoo 2 la tecnología SLI (Scan-Line Interleave) con la que se podían conectar dos tarjetas gráficas en paralelo, lo cual además de una buena estrategia de ventas fueron los inicios de la computación gráfica en multiples procesadores, 3Dfx innovaba mucho y finalmente fue comprada por Nvidia.

Más tarde la salida de DirectX 8 intentó mejorar esto incorporando la posibilidad de poder escribir pequeños programas que serían ejecutados por la GPU para cada vértice y cada pixel, esto aportó gran flexibilidad al desarrollo de efectos gráficos. Estos pequeños programas se llamaban Shaders y al conjunto de especificaciones se le llamó Shader Model el cual podía dividirse en dos conjuntos las especificaciones para trabajar con vértices llamada Vertex Shader y las especificaciones para trabajar a nivel de pixel llamadas Pixel Shader.

Microsoft lanzaba las especificaciones de cada versión de Shader Model pero las primeras tarjetas en incorporar soporte para shaders implementaban parcialmente dichas especificaciones por ello no se hablaba casi nunca de Shader Model y se especificaba hasta que versión de Pixel Shader y Vertex Shader soportaban que no tenían porque ser la misma. Sin embargo a patir de la versión 2.0 de Shader Model los fabricantes empezaron ha hablar ya de Shader Model lo cual indicaba que las tarjetas soportaban tanto Vertex Shader 2.0 como Pixel Shader 2.0.

Por aquellos tiempos la programación de shader era muy similar a la programación en emsamblador:

Vertex Shader

vs_1_1 // version instruction

#define fogStart c9.x

#define fogEnd c9.z

def c9, 2, 2.33, 2.66, 3 // fog start values

def c10, 3, 4.5, 6, 10 // fog end values

def c11, 0, 0, 1, 1 // clamping values

def c13, 0.66, 1.51, 0, 0

 

dcl_position v0 

dcl_texcoord v7

m4x4 r0, v0, c0  // transform vertices by world-view-projection matrix

mov oPos, r0

mov oT0, v7

m4x4 r1, v0, c4  // transform vertices by world-view matrix

// fog constants calculated in the application (6 instructions)

mov r2.x, c13.y  // 1 / (fog end - fog start)

sub r2.y, fogEnd, r1.z // (fog end - distance)

mul r2.z, r2.y, r2.x  // (fog end - distance)/(fog end - fog start)

max r2.w, c11.x, r2.z  // clamp above 0

min r2.w, c11.z, r2.z  // clamp below 1

mov oFog, r2.w  // output per-vertex fog factor in r2.x

 

Pixel Shader

ps_1_1 // version instruction

def c0, 0,0,0,0

def c1, 1,1,1,1

def c2, 1.0,0.5,0,0

def c3, 0,-0.5,-0.25,0

tex t0 // sample texture at stage 0,

// with texture coordinate set 0

mov r0, t0 // output texture color

// mov r0, 1 - t0 // output inverted texture color

// add r0, t0, c2 // add more reds and greens

// add r0, t0, c3 // subtract greens and blues

// mov r0, c2 // output solid pixel color

Lo cual hacía muy complicada su escritura, mantenimiento y reutilización, por esta razón se decidió crear lenguajes de alto nivel para la programación de Shader los cuales fuese compilados.

Microsoft desarrollo el lenguaje HLSL (High Level Shading Language) similar a C el cual lanzó con la versión de DirectX 9, esto provocó un impulso en en el mundo de los gráficos 3D, ahora era mucho más fácil escribir Shaders y por lo tanto el tamaño de estos pequeños programas fue aumentando al igual que su API.

También se desarrolló un lenguaje de alto nivel para trabajar bajo OpenGL llamado GLSL y posteriormente Nvidia lanzó un lenguaje más, llamado CG el cual permite compilar fácilmente un Shader a CG o HLSL.

Aquí podéis ver un ejemplo de un Shader básico que contiene su función para Vertex y Pixel Shader:

float4x4 WorldViewProjection;

 

float4 VertexShaderFunction(float4 Position : POSITION) : POSITION

{

    return mul(Position, WorldViewProjection);

}

 

float4 PixelShaderFunction() : COLOR

{

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

}

 

technique Technique1

{

    pass Pass1

    {

        VertexShader = compile vs_1_1 VertexShaderFunction();

        PixelShader = compile ps_1_1 PixelShaderFunction();

    }

}

 

Tras programar en HLSL nunca más quieres volver a saber nada sobre lo anterior pero siempre es importante conocer algo de lo que había antes, la evolución de la API con cada versión de DirectX ha sido la siguiente:

  • DirectX 8.0 y 8.1 Shader Model 1.0
  • DirectX 9.0 Shader Model 2.0
  • DirectX 9.0c Shader Model 3.0
  • DirectX 10 y 10.1 Shader Model 4.0
  • DirectX 11 Shader Model 5.0

Cada una de estas versiones ha venido acompañada de mejoras, tanto en el número de instrucciones que se podían introduccir en cada shader (sin restricción alguna en las últimas versiones), como al número de intrisic functions disponibles. Cabe destar que XNA (hasta la versión actual XNA 3.1) está desarrollada sobre DirectX 9.0c por lo que desde este framework solo tenemos acceso a las especificaciones de Shader Model 3.0.

En la actualidad se ha lanzado ya la versión 11 de DirectX la cual da incluso un paso más allá con el DirectCompute del cual hablaremos otro día.

Publicado por

jcanton

Javier is a Computer Science Engineer who has always had a passion for 3D graphics and software architecture. He learned C# almost at the same time as he learned to talk, and his first word was "base". He enjoys imparting talks about technology and has contributed in many important software and video game events. He has participated in multitude of software projects involving multitouch technologies, innovative user interfaces, augmented reality, and video games. Some of these projects were developed for companies such as Microsoft, Syderis, and nVidia. His professional achievements include being MVP for Windows DirectX and DirectX XNA for the last eight years, Xbox Ambassador, as well as Microsoft Student Partner and Microsoft Most Valuable Student during his years at college. Currently he works at Plainconcepts and he is the development team lead at WaveEngine project.

5 comentarios sobre “HLSL, Un poco de historia”

  1. Bonita historia 🙂

    PD: Hace unos días que me estoy poniendo las pilas con los shaders… espero que no lo cambien todo con la versión 4 del Game Studio…

  2. Te has olvidado de hablar de los shaders de Quake 3, que eran poco mas que conjuntos de instrucciones y efectos de OpenGL que se aplicarian al dibujar determinado material 😛

Deja un comentario

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