将普通数据传递给着色器

时间:2015-02-28 23:50:58

标签: c++ directx shader directx-11 vertex-shader

我编写了使用DirectX 11渲染一些对象的简单代码。

该位置已正确传递给着色器。但是,法线似乎在某处丢失。我更改了着色器以查看法线'值作为一种颜色(只是一个调试目的),我得到黑盒子(每个顶点的0,0,0法线?),在正确的位置:

enter image description here

请注意,在右栏上我可以看到我的NORMAL值(它们是正确的!),但在"当地人" 仅设置position,其余值为NaN。为什么?

closer look


着色器:

... //some constants

struct VertexInputType
{
    float4 position : POSITION;
    float2 tex : TEXCOORD;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
    //float3 binormal : BINORMAL;
};

struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float4 worldPos : POSITION;
    float2 TexCoord : TEXCOORD;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
};

//VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD, float3 inNormal : NORMAL, float3 tangent : TANGENT)
VS_OUTPUT VS(VertexInputType input)
{
    VS_OUTPUT output;
    output.Pos = mul(input.position, WVP);
    output.worldPos = mul(input.position, World);
    output.normal = input.normal;
    return output;
}

float4 PS(VS_OUTPUT input) : SV_TARGET
{
    return float4(input.normal*100, 1);
}

technique10 RENDER
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
       // SetGeometryShader( CompileShader( gs_4_0, GS() ) );       
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
        SetBlendState( SrcAlphaBlendingAdd, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }    
}

在渲染过程中,我使用:

UINT stride = sizeof(Vertex);
UINT offset = 0;
context->IASetVertexBuffers(0, 1, &buffers->vertexBuffer, &stride, &offset); //set vertex buffer
context->IASetIndexBuffer(buffers->indexBuffer, DXGI_FORMAT_R16_UINT, 0); //set index buffer

for(int i=0; i<structure.subsets.size(); i++){
    //set matrices
    DirectX::XMFLOAT4X4 view = camera->getView();
    DirectX::XMMATRIX camView = XMLoadFloat4x4(&view);
    DirectX::XMFLOAT4X4 projection = camera->getProjection();
    DirectX::XMMATRIX camProjection = XMLoadFloat4x4(&projection);
    DirectX::XMMATRIX worldViewProjectionMatrix = objectWorldMatrix * camView * camProjection;

    //set the constants per object
    ConstantBufferStructure constantsPerObject;
    constantsPerObject.worldViewProjection = XMMatrixTranspose(worldViewProjectionMatrix);  
    constantsPerObject.world = XMMatrixTranspose(objectWorldMatrix);

    //bind constants per object to constant buffer and send it to vertex and pixel shaders
    context->UpdateSubresource(constantBuffer, 0, NULL, &constantsPerObject, 0, 0);
    context->VSSetConstantBuffers(0, 1, &constantBuffer);
    context->PSSetConstantBuffers(0, 1, &constantBuffer);

    //context->PSSetSamplers(0,1,&m_sampleState);
    context->RSSetState(RSCullDefault);
    int start = structure.subsets[i]->getVertexIndexStart();
    int count = structure.subsets[i]->getVertexIndexAmmount();
    context->DrawIndexed(count, start, 0);
}

对于着色器初始化:

// Create the vertex shader
hr = device->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &vertexShader );

//create the input layout
VertexLayoutDescirption layoutDescription; //will gives us the data that is corresponding with Vertex structure
hr = device->CreateInputLayout(layoutDescription.layout, layoutDescription.entriesCount, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &*vertexLayout );
pVSBlob->Release();
context->IASetInputLayout( *vertexLayout );

//compile the pixel shader
ID3DBlob* pPSBlob = NULL;
CompileShaderFromFile( C::toWChar(C::toString(pixelShaderFileName)), "PS", "ps_4_0", &pPSBlob );

// Create the pixel shader
hr = device->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &pixelShader );

其中:

struct Vertex{//vertex structure
    Vertex() : weightCount(0){}
    Vertex(float x, float y, float z, float u, float v, float nx, float ny, float nz, float tx, float ty, float tz)
        : position(x, y, z), textureCoordinates(u, v), normals(nx, ny, nz), tangents(tx, ty, tz), weightCount(0){}
    Vertex(DirectX::XMFLOAT3 position, DirectX::XMFLOAT2 textureCoordinates, DirectX::XMFLOAT3 normals, DirectX::XMFLOAT3 biTangents)
        : position(position), textureCoordinates(textureCoordinates), normals(normals), tangents(tangents), weightCount(0){}

    DirectX::XMFLOAT3 position;
    DirectX::XMFLOAT2 textureCoordinates;
    DirectX::XMFLOAT3 normals;
    DirectX::XMFLOAT3 tangents;
    DirectX::XMFLOAT3 biTangents;

    //will not be sent to shader (and used only by skinned models)
    int startWeightIndex; //index in Subset::weights (from 0 to X for each subset separately)
    int weightCount; //=0 means that it's not skinned vertex
};

/* will be used by Shader, should be corresponding th Vertex (the data that we want to transfer to shader) */
struct VertexLayoutDescirption{
    D3D11_INPUT_ELEMENT_DESC layout[4]; //the input layout
    UINT entriesCount; //the numer of elements of layout[], will be also used by Shader

    VertexLayoutDescirption(){
        entriesCount = 4;
        for(UINT i=0; i<entriesCount; i++){
            layout[i].SemanticIndex = 0; 
            layout[i].Format = DXGI_FORMAT_R32G32B32_FLOAT; 
            layout[i].InputSlot = 0; 
            layout[i].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 
            layout[i].InstanceDataStepRate = 0;
        }

        layout[0].SemanticName ="POSITION"; 
        layout[0].AlignedByteOffset = 0; //(not D3D11_APPEND_ALIGNED_ELEMENT)

        layout[1].SemanticName ="TEXCOORD"; 
        layout[1].AlignedByteOffset = 12; //or D3D11_APPEND_ALIGNED_ELEMENT

        layout[2].SemanticName ="NORMAL"; 
        layout[2].AlignedByteOffset = 20; //or D3D11_APPEND_ALIGNED_ELEMENT

        layout[3].SemanticName ="TANGENT"; 
        layout[3].AlignedByteOffset = 32; //or D3D11_APPEND_ALIGNED_ELEMENT
    }
};

盒子模型:

/*top vertices*/
structure.vertices[0] = Vertex(/*pos*/ -1.0f, +1.0f, -1.0f, /*uv*/ 1.0f, 1.0f, /*normals*/ 0.0f, 1.0f, -1.0f, /*tan*/ +1.0f, -1.0f, 1.0f);
structure.vertices[1] = Vertex(/*pos*/ +1.0f, +1.0f, -1.0f, /*uv*/ 0.0f, 1.0f, /*normals*/ 0.0f, 1.0f, +1.0f, /*tan*/ +1.0f, -1.0f, 1.0f);
structure.vertices[2] = Vertex(/*pos*/ +1.0f, +1.0f, +1.0f, /*uv*/ 1.0f, 0.0f, /*normals*/ 0.0f, 1.0f, +1.0f, /*tan*/ +1.0f, +1.0f, 1.0f);
structure.vertices[3] = Vertex(/*pos*/ -1.0f, +1.0f, +1.0f, /*uv*/ 0.0f, 0.0f, /*normals*/ 0.0f, 1.0f, -1.0f, /*tan*/ +1.0f, +1.0f, 1.0f);

/*bottom vertices*/                                                                                            
structure.vertices[4] = Vertex(/*pos*/ -1.0f, -1.0f, -1.0f, /*uv*/ 1.0f, 0.0f, /*normals*/ 0.0f, 1.0f, -1.0f, /*tan*/ -1.0f, -1.0f, 1.0f);
structure.vertices[5] = Vertex(/*pos*/ +1.0f, -1.0f, -1.0f, /*uv*/ 0.0f, 0.0f, /*normals*/ 0.0f, 1.0f, +1.0f, /*tan*/ -1.0f, -1.0f, 1.0f);
structure.vertices[6] = Vertex(/*pos*/ +1.0f, -1.0f, +1.0f, /*uv*/ 1.0f, 1.0f, /*normals*/ 0.0f, 1.0f, +1.0f, /*tan*/ -1.0f, +1.0f, 1.0f);
structure.vertices[7] = Vertex(/*pos*/ -1.0f, -1.0f, +1.0f, /*uv*/ 0.0f, 1.0f, /*normals*/ 0.0f, 1.0f, -1.0f, /*tan*/ -1.0f, +1.0f, 1.0f);

buffers = new Buffers();

D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT; //D3D11_USAGE_DYNAMIC
bd.ByteWidth = sizeof(Vertex) * structure.getVerticesCount();
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory(&InitData, sizeof(InitData));
InitData.pSysMem = structure.vertices;
if(device->CreateBuffer(&bd, &InitData, &buffers->vertexBuffer) != S_OK){
    return false;
}

... //index buffer

为什么在这个位置没有将法线传递给着色器?我错过了什么?

1 个答案:

答案 0 :(得分:0)

在着色器文件中,尝试在float3 normal : TEXCOORD1;结构中使用float3 normal : TEXCOORD2;TEXCOORD或任何语义float3 normal : NORMAL;与任何索引而不是VS_OUTPUT