Initialize the shader

Posted cookiebox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Initialize the shader相关的知识,希望对你有一定的参考价值。

目录

Loads the shader files and makes it usable to DirectX and the GPU

Now we will start with one of the more important functions to this tutorial which is called InitializeShader. This function is what actually loads the shader files and makes it usable to DirectX and the GPU. You will also see the setup of the layout and how the vertex buffer data is going to look on the graphics pipeline in the GPU. The layout will need the match the VertexType in the modelclass.h file as well as the one defined in the color.vs file.

bool ColorShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename)
{
    HRESULT result;
    ID3D10Blob* errorMessage;
    ID3D10Blob* vertexShaderBuffer;
    ID3D10Blob* pixelShaderBuffer;
    D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
    unsigned int numElements;
    D3D11_BUFFER_DESC matrixBufferDesc;


    // Initialize the pointers this function will use to null.
    errorMessage = 0;
    vertexShaderBuffer = 0;
    pixelShaderBuffer = 0;

Compile the shader programs into buffers

Here is where we compile the shader programs into buffers. We give it the name of the shader file, the name of the shader, the shader version (5.0 in DirectX 11), and the buffer to compile the shader into. If it fails compiling the shader it will put an error message inside the errorMessage string which we send to another function to write out the error. If it still fails and there is no errorMessage string then it means it could not find the shader file in which case we pop up a dialog box saying so.

    // Compile the vertex shader code.
    result = D3DCompileFromFile(vsFilename, NULL, NULL, "ColorVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0,
                    &vertexShaderBuffer, &errorMessage);
    if(FAILED(result))
    {
        // If the shader failed to compile it should have writen something to the error message.
        if(errorMessage)
        {
            OutputShaderErrorMessage(errorMessage, hwnd, vsFilename);
        }
        // If there was  nothing in the error message then it simply could not find the shader file itself.
        else
        {
            MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK);
        }

        return false;
    }

    // Compile the pixel shader code.
    result = D3DCompileFromFile(psFilename, NULL, NULL, "ColorPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0,
                    &pixelShaderBuffer, &errorMessage);
    if(FAILED(result))
    {
        // If the shader failed to compile it should have writen something to the error message.
        if(errorMessage)
        {
            OutputShaderErrorMessage(errorMessage, hwnd, psFilename);
        }
        // If there was nothing in the error message then it simply could not find the file itself.
        else
        {
            MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK);
        }

        return false;
    }

D3DCompileFromFile function

Note You can use this API to develop your Windows Store apps, but you can‘t use it in apps that you submit to the Windows Store. Refer to the section, "Compiling shaders for UWP", in the remarks for D3DCompile2.

Compiles Microsoft High Level Shader Language (HLSL) code into bytecode for a given target.
Syntax


HRESULT D3DCompileFromFile(
  LPCWSTR                pFileName,
  const D3D_SHADER_MACRO *pDefines,
  ID3DInclude            *pInclude,
  LPCSTR                 pEntrypoint,
  LPCSTR                 pTarget,
  UINT                   Flags1,
  UINT                   Flags2,
  ID3DBlob               **ppCode,
  ID3DBlob               **ppErrorMsgs
);

Parameters
pFileName

A pointer to a constant null-terminated string that contains the name of the file that contains the shader code.

pDefines

An optional array of D3D_SHADER_MACRO structures that define shader macros. Each macro definition contains a name and a NULL-terminated definition. If not used, set to NULL.

pInclude

An optional pointer to an ID3DInclude interface that the compiler uses to handle include files. If you set this parameter to NULL and the shader contains a #include, a compile error occurs. You can pass the D3D_COMPILE_STANDARD_FILE_INCLUDE macro, which is a pointer to a default include handler. This default include handler includes files that are relative to the current directory.

#define D3D_COMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude*)(UINT_PTR)1)

pEntrypoint

A pointer to a constant null-terminated string that contains the name of the shader entry point function where shader execution begins. When you compile an effect, D3DCompileFromFile ignores pEntrypoint; we recommend that you set pEntrypoint to NULL because it is good programming practice to set a pointer parameter to NULL if the called function will not use it.

pTarget

A pointer to a constant null-terminated string that specifies the shader target or set of shader features to compile against. The shader target can be a shader model (for example, shader model 2, shader model 3, shader model 4, or shader model 5 and later). The target can also be an effect type (for example, fx_4_1). For info about the targets that various profiles support, see Specifying Compiler Targets.

Flags1

A combination of shader compile options that are combined by using a bitwise OR operation. The resulting value specifies how the compiler compiles the HLSL code.

Flags2

A combination of effect compile options that are combined by using a bitwise OR operation. The resulting value specifies how the compiler compiles the effect. When you compile a shader and not an effect file, D3DCompileFromFile ignores Flags2; we recommend that you set Flags2 to zero because it is good programming practice to set a nonpointer parameter to zero if the called function will not use it.

ppCode

A pointer to a variable that receives a pointer to the ID3DBlob interface that you can use to access the compiled code.

ppErrorMsgs

An optional pointer to a variable that receives a pointer to the ID3DBlob interface that you can use to access compiler error messages, or NULL if there are no errors.


Create the shader objects

Once the vertex shader and pixel shader code has successfully compiled into buffers we then use those buffers to create the shader objects themselves. We will use these pointers to interface with the vertex and pixel shader from this point forward.

    // Create the vertex shader from the buffer.
    result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader);
    if(FAILED(result))
    {
        return false;
    }

    // Create the pixel shader from the buffer.
    result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader);
    if(FAILED(result))
    {
        return false;
    }

ID3D11Device::CreateVertexShader method

Create a vertex-shader object from a compiled shader.

Syntax


HRESULT CreateVertexShader(
  const void         *pShaderBytecode,
  SIZE_T             BytecodeLength,
  ID3D11ClassLinkage *pClassLinkage,
  ID3D11VertexShader **ppVertexShader
);

Parameters
pShaderBytecode

Type: const void*

A pointer to the compiled shader.

BytecodeLength

Type: SIZE_T

Size of the compiled vertex shader.

pClassLinkage

Type: ID3D11ClassLinkage*

A pointer to a class linkage interface (see ID3D11ClassLinkage); the value can be NULL.

ppVertexShader

Type: ID3D11VertexShader**

Address of a pointer to a ID3D11VertexShader interface. If this is NULL, all other parameters will be validated, and if all parameters pass validation this API will return S_FALSE instead of S_OK.

Return Value

Type: HRESULT

This method returns one of the Direct3D 11 Return Codes.

Remarks
The Direct3D 11.1 runtime, which is available starting with Windows 8, provides the following new functionality for CreateVertexShader.

The following shader model 5.0 instructions are available to just pixel shaders and compute shaders in the Direct3D 11.0 runtime. For the Direct3D 11.1 runtime, because unordered access views (UAV) are available at all shader stages, you can use these instructions in all shader stages.

Therefore, if you use the following shader model 5.0 instructions in a vertex shader, you can successfully pass the compiled vertex shader to pShaderBytecode. That is, the call to CreateVertexShader succeeds.

If you pass a compiled shader to pShaderBytecode that uses any of the following instructions on a device that doesn’t support UAVs at every shader stage (including existing drivers that are not implemented to support UAVs at every shader stage), CreateVertexShader fails. CreateVertexShader also fails if the shader tries to use a UAV slot beyond the set of UAV slots that the hardware supports.

  • dcl_uav_typed
  • dcl_uav_raw
  • dcl_uav_structured
  • ld_raw
  • ld_structured
  • ld_uav_typed
  • store_raw
  • store_structured
  • store_uav_typed
  • sync_uglobal

All atomics and immediate atomics (for example, atomic_and and imm_atomic_and)


Create the layout of the vertex data

The next step is to create the layout of the vertex data that will be processed by the shader. As this shader uses a position and color vector we need to create both in the layout specifying the size of both. The semantic name is the first thing to fill out in the layout, this allows the shader to determine the usage of this element of the layout. As we have two different elements we use POSITION for the first one and COLOR for the second. The next important part of the layout is the Format. For the position vector we use DXGI_FORMAT_R32G32B32_FLOAT and for the color we use DXGI_FORMAT_R32G32B32A32_FLOAT. The final thing you need to pay attention to is the AlignedByteOffset which indicates how the data is spaced in the buffer. For this layout we are telling it the first 12 bytes are position and the next 16 bytes will be color, AlignedByteOffset shows where each element begins. You can use D3D11_APPEND_ALIGNED_ELEMENT instead of placing your own values in AlignedByteOffset and it will figure out the spacing for you. The other settings I‘ve made default for now as they are not needed in this tutorial.

    // Create the vertex input layout description.
    // This setup needs to match the VertexType stucture in the ModelClass and in the shader.
    polygonLayout[0].SemanticName = "POSITION";
    polygonLayout[0].SemanticIndex = 0;
    polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
    polygonLayout[0].InputSlot = 0;
    polygonLayout[0].AlignedByteOffset = 0;
    polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    polygonLayout[0].InstanceDataStepRate = 0;

    polygonLayout[1].SemanticName = "COLOR";
    polygonLayout[1].SemanticIndex = 0;
    polygonLayout[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
    polygonLayout[1].InputSlot = 0;
    polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
    polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    polygonLayout[1].InstanceDataStepRate = 0;

D3D11_INPUT_ELEMENT_DESC structure

A description of a single element for the input-assembler stage.

Syntax


typedef struct D3D11_INPUT_ELEMENT_DESC {
  LPCSTR                     SemanticName;
  UINT                       SemanticIndex;
  DXGI_FORMAT                Format;
  UINT                       InputSlot;
  UINT                       AlignedByteOffset;
  D3D11_INPUT_CLASSIFICATION InputSlotClass;
  UINT                       InstanceDataStepRate;
} D3D11_INPUT_ELEMENT_DESC;

Members
SemanticName

Type: LPCSTR

The HLSL semantic associated with this element in a shader input-signature.

SemanticIndex

Type: UINT

The semantic index for the element. A semantic index modifies a semantic, with an integer index number. A semantic index is only needed in a case where there is more than one element with the same semantic. For example, a 4x4 matrix would have four components each with the semantic name

matrix

, however each of the four component would have different semantic indices (0, 1, 2, and 3).

Format

Type: DXGI_FORMAT

The data type of the element data. See DXGI_FORMAT.

InputSlot

Type: UINT

An integer value that identifies the input-assembler (see input slot). Valid values are between 0 and 15, defined in D3D11.h.

AlignedByteOffset

Type: UINT

Optional. Offset (in bytes) between each element. Use D3D11_APPEND_ALIGNED_ELEMENT for convenience to define the current element directly after the previous one, including any packing if necessary.

InputSlotClass

Type: D3D11_INPUT_CLASSIFICATION

Identifies the input data class for a single input slot (see D3D11_INPUT_CLASSIFICATION).

InstanceDataStepRate

Type: UINT

The number of instances to draw using the same per-instance data before advancing in the buffer by one element. This value must be 0 for an element that contains per-vertex data (the slot class is set to D3D11_INPUT_PER_VERTEX_DATA).


CreateInputLayout

Once the layout description has been setup we can get the size of it and then create the input layout using the D3D device. Also release the vertex and pixel shader buffers since they are no longer needed once the layout has been created.

// Get a count of the elements in the layout.
numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

// Create the vertex input layout.
result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), 
                   vertexShaderBuffer->GetBufferSize(), &m_layout);
if(FAILED(result))
{
    return false;
}

// Release the vertex shader buffer and pixel shader buffer since they are no longer needed.
vertexShaderBuffer->Release();
vertexShaderBuffer = 0;

pixelShaderBuffer->Release();
pixelShaderBuffer = 0;

ID3D11Device::CreateInputLayout method

Create an input-layout object to describe the input-buffer data for the input-assembler stage.

Syntax


HRESULT CreateInputLayout(
  const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
  UINT                           NumElements,
  const void                     *pShaderBytecodeWithInputSignature,
  SIZE_T                         BytecodeLength,
  ID3D11InputLayout              **ppInputLayout
);

Parameters
pInputElementDescs

Type: const D3D11_INPUT_ELEMENT_DESC*

An array of the input-assembler stage input data types; each type is described by an element description (see D3D11_INPUT_ELEMENT_DESC).

NumElements

Type: UINT

The number of input-data types in the array of input-elements.

pShaderBytecodeWithInputSignature

Type: const void*

A pointer to the compiled shader. The compiled shader code contains a input signature which is validated against the array of elements. See remarks.

BytecodeLength

Type: SIZE_T

Size of the compiled shader.

ppInputLayout

Type: ID3D11InputLayout**

A pointer to the input-layout object created (see ID3D11InputLayout). To validate the other input parameters, set this pointer to be NULL and verify that the method returns S_FALSE.

constant buffer

The final thing that needs to be setup to utilize the shader is the constant buffer. As you saw in the vertex shader we currently have just one constant buffer so we only need to setup one here so we can interface with the shader. The buffer usage needs to be set to dynamic since we will be updating it each frame. The bind flags indicate that this buffer will be a constant buffer. The cpu access flags need to match up with the usage so it is set to D3D11_CPU_ACCESS_WRITE. Once we fill out the description we can then create the constant buffer interface and then use that to access the internal variables in the shader using the function SetShaderParameters.

// Setup the description of the dynamic matrix constant buffer that is in the vertex shader.
matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
matrixBufferDesc.MiscFlags = 0;
matrixBufferDesc.StructureByteStride = 0;

// Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class.
result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer);
if(FAILED(result))
{
    return false;
}

return true;

}

ID3D11Device::CreateInputLayout method

Create an input-layout object to describe the input-buffer data for the input-assembler stage.

Syntax
C++

HRESULT CreateInputLayout(
const D3D11_INPUT_ELEMENT_DESC pInputElementDescs,
UINT NumElements,
const void
pShaderBytecodeWithInputSignature,
SIZE_T BytecodeLength,
ID3D11InputLayout ppInputLayout
);
Parameters
pInputElementDescs**

Type: const D3D11_INPUT_ELEMENT_DESC*

An array of the input-assembler stage input data types; each type is described by an element description (see D3D11_INPUT_ELEMENT_DESC).

NumElements

Type: UINT

The number of input-data types in the array of input-elements.

pShaderBytecodeWithInputSignature

Type: const void*

A pointer to the compiled shader. The compiled shader code contains a input signature which is validated against the array of elements. See remarks.

BytecodeLength

Type: SIZE_T

Size of the compiled shader.

ppInputLayout

Type: ID3D11InputLayout**

A pointer to the input-layout object created (see ID3D11InputLayout). To validate the other input parameters, set this pointer to be NULL and verify that the method returns S_FALSE.
















以上是关于Initialize the shader的主要内容,如果未能解决你的问题,请参考以下文章

我的OpenGL学习进阶之旅解决着色器语法错误:The shader uses varying u_Color, but previous shader does not write to it

我的OpenGL学习进阶之旅解决着色器语法错误:The shader uses varying u_Color, but previous shader does not write to it

Cg入门19:Fragment shader - 片段级模型动态变色

Cg入门20:Fragment shader - 片段级模型动态变色(实现汽车动态换漆)

Shader2.0的顶点着色器和片段着色器

Shader HLSL片段说明