Uso de sombreadores en Direct3D 10

La canalización tiene tres fases de sombreador y cada una está programada con un sombreador HLSL. Todos los sombreadores de Direct3D 10 se escriben en HLSL, que tienen como destino el modelo de sombreador 4.

Diferencias entre Direct3D 9 y Direct3D 10:

  • A diferencia de los modelos de sombreador de Direct3D 9 que podrían crearse en un lenguaje de ensamblado intermedio, los sombreadores del modelo de sombreador 4.0 solo se crean en HLSL. Todavía se admite la compilación sin conexión de sombreadores en código de bytes consumible para dispositivos y se recomienda para la mayoría de los escenarios.

En este ejemplo solo se usa un sombreador de vértices. Dado que todos los sombreadores se crean a partir del núcleo común del sombreador, aprender a usar un sombreador de vértices es muy similar al uso de un sombreador de píxeles o geometría.

Una vez que haya creado un sombreador HLSL (en este ejemplo se usa el sombreador de vértices HLSLWithoutFX.vsh), deberá prepararlo para la fase de canalización determinada que la usará. Para ello, debe:

Estos pasos deben repetirse para cada sombreador de la canalización.

Compilar un sombreador

El primer paso es compilar el sombreador para comprobar que ha codificado correctamente las instrucciones HLSL. Esto se hace llamando a D3D10CompileShader y proporcionándolo con varios parámetros, como se muestra aquí:

    IPD3D10Blob * pBlob;
    
        
    // Compile the vertex shader from the file
    D3D10CompileShader( strPath, strlen( strPath ), "HLSLWithoutFX.vsh", 
        NULL, NULL, "Ripple", "vs_4_0", dwShaderFlags, &pBlob, NULL );

Esta función toma los parámetros siguientes:

  • Nombre del archivo ( y longitud de la cadena de nombre en bytes ) que contiene el sombreador. En este ejemplo solo se usa un sombreador de vértices (en el archivo HLSLWithoutFX.vsh donde la extensión de archivo .vsh es una abreviatura del sombreador de vértices).

  • Nombre de la función de sombreador. En este ejemplo se compila un sombreador de vértices de la función Ripple que toma una sola entrada y devuelve una estructura de salida (la función procede del ejemplo HLSLWithoutFX):

    VS_OUTPUT Ripple( in float2 vPosition : POSITION )
    
  • Puntero a todas las macros usadas por el sombreador. Use D3D10_SHADER_MACRO para ayudar a definir las macros; simplemente cree una cadena de nombre que contenga todos los nombres de macro (con cada nombre separado por un espacio) y una cadena de definición (con cada cuerpo de macro separado por un espacio). Ambas cadenas deben terminarse en NULL.

  • Puntero a cualquier otro archivo que necesite incluir para que los sombreadores se compilen. Usa la interfaz ID3D10Include que tiene dos métodos implementados por el usuario: Open y Close. Para que esto funcione, deberá implementar el cuerpo de los métodos Open y Close; En el método Open, agregue el código que usaría para abrir los archivos de inclusión que desee, en la función Close, agregue el código para cerrar los archivos cuando haya terminado con ellos.

  • Nombre de la función de sombreador que se va a compilar. Este sombreador compila la función Ripple.

  • Perfil del sombreador que se va a establecer como destino al compilar. Puesto que puede compilar una función en un sombreador de vértices, geometría o píxeles, el perfil indica al compilador qué tipo de sombreador y qué modelo de sombreador comparar el código.

  • Marcas del compilador del sombreador. Estas marcas indican al compilador qué información colocar en la salida compilada y cómo desea optimizar el código de salida: para velocidad, para depurar, etc. Consulte Constantes de efecto (Direct3D 10) para obtener una lista de las marcas disponibles. El ejemplo contiene código que puede usar para establecer los valores de marca del compilador para el proyecto; esto es principalmente una cuestión de si desea generar o no información de depuración.

  • Puntero al búfer que contiene el código del sombreador compilado. El búfer también contiene cualquier información de tabla de símbolos y depuración incrustada solicitada por las marcas del compilador.

  • Puntero a un búfer que contiene una lista de errores y advertencias que se encontraron durante la compilación, que son los mismos mensajes que vería en la salida de depuración si estaba ejecutando el depurador mientras compilaba el sombreador. NULL es un valor aceptable cuando no quiere que se devuelvan los errores a un búfer.

Si el sombreador se compila correctamente, se devuelve un puntero al código del sombreador como una interfaz ID3D10Blob. Se denomina interfaz blob porque el puntero es a una ubicación en memoria formada por una matriz de DWORD. La interfaz se proporciona para que pueda obtener un puntero al sombreador compilado que necesitará en el paso siguiente.

A partir del SDK de diciembre de 2006, el compilador HLSL de DirectX 10 ahora es el compilador predeterminado en DirectX 9 y DirectX 10. Consulte Effect-Compiler Tool (Herramienta del compilador de efectos ) para obtener más información.

Obtener un puntero a un sombreador compilado

Varios métodos de API requieren un puntero a un sombreador compilado. Este argumento se suele denominar pShaderBytecode porque apunta a un sombreador compilado representado como una secuencia de códigos de bytes. Para obtener un puntero a un sombreador compilado, primero compile el sombreador llamando a D3D10CompileShader o una función similar. Si la compilación es correcta, el sombreador compilado se devuelve en una interfaz ID3D10Blob . Por último, use el método GetBufferPointer para devolver el puntero.

Crear un objeto shader

Una vez compilado el sombreador, llame a CreateVertexShader para crear el objeto de sombreador:

    ID3D10VertexShader ** ppVertexShader
    ID3D10Blob pBlob;


    // Create the vertex shader
    hr = pd3dDevice->CreateVertexShader( (DWORD*)pBlob->GetBufferPointer(),
        pBlob->GetBufferSize(), &ppVertexShader );

    // Release the pointer to the compiled shader once you are done with it
    pBlob->Release();

Para crear el objeto de sombreador, pase el puntero al sombreador compilado a CreateVertexShader. Dado que primero tuvo que compilar correctamente el sombreador, esta llamada casi seguramente pasará, a menos que tenga un problema de memoria en la máquina.

Puede crear tantos objetos de sombreador como desee y simplemente mantener punteros a ellos. Este mismo mecanismo funciona para sombreadores de geometría y píxeles, suponiendo que coincida con los perfiles de sombreador (cuando se llama al método de compilación) a los nombres de interfaz (cuando se llama al método create).

Establecer el objeto Shader

El último paso es establecer el sombreador en la fase de canalización. Dado que hay tres fases de sombreador en la canalización, deberá realizar tres llamadas API, una para cada fase.

    // Set a vertex shader
    pd3dDevice->VSSetShader( g_pVS10 );

La llamada a VSSetShader toma el puntero al sombreador de vértices creado en el paso 1. Esto establece el sombreador en el dispositivo. La fase del sombreador de vértices ahora se inicializa con su código de sombreador de vértices, todo lo que queda es inicializar cualquier variable de sombreador.

Repetir para las 3 fases del sombreador

Repita este mismo conjunto de pasos para compilar cualquier sombreador de vértices o píxeles o incluso un sombreador de geometría que se genere en el sombreador de píxeles.

Compilación de sombreadores

Guía de programación para HLSL