Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Här visar vi hur du använder HLSL-källfiler för att kompilera och skapa skuggningar som du sedan kan använda för att rita primitiver på skärmen.
Vi skapar och ritar en gul triangel med hörn och pixelskuggor. När vi har skapat Direct3D-enheten, växlingskedjan och vyn render-target läser vi data från binära skuggningsobjektfiler på disken.
Objektiv: Skapa skuggningar och rita primitiver.
Förutsättningar
Vi antar att du är bekant med C++. Du behöver också grundläggande erfarenhet av grafikprogrammeringsbegrepp.
Vi antar också att du har gått igenom Snabbstart: konfigurera DirectX-resurser och visa en bild.
Tid att slutföra: 20 minuter.
Instruktion
1. Kompilera HLSL-källfiler
Microsoft Visual Studio använder fxc.exe HLSL-kodkompileraren för att kompilera .hlsl-källfilerna (SimpleVertexShader.hlsl och SimplePixelShader.hlsl) till .cso binära skuggobjektfiler (SimpleVertexShader.cso och SimplePixelShader.cso). Mer information om HLSL-kodkompilatorn finns i Effect-Compiler Tool. Mer information om hur du kompilerar skuggningskod finns i Kompilera skuggningar.
Här är koden i SimpleVertexShader.hlsl:
struct VertexShaderInput
{
DirectX::XMFLOAT2 pos : POSITION;
};
struct PixelShaderInput
{
float4 pos : SV_POSITION;
};
PixelShaderInput SimpleVertexShader(VertexShaderInput input)
{
PixelShaderInput vertexShaderOutput;
// For this lesson, set the vertex depth value to 0.5, so it is guaranteed to be drawn.
vertexShaderOutput.pos = float4(input.pos, 0.5f, 1.0f);
return vertexShaderOutput;
}
Här är koden i SimplePixelShader.hlsl:
struct PixelShaderInput
{
float4 pos : SV_POSITION;
};
float4 SimplePixelShader(PixelShaderInput input) : SV_TARGET
{
// Draw the entire triangle yellow.
return float4(1.0f, 1.0f, 0.0f, 1.0f);
}
2. Läsa data från disk
Vi använder funktionen DX::ReadDataAsync från DirectXHelper.h i DirectX 11-appmallen (Universell Windows) för att asynkront läsa data från en fil på disken.
3. Skapa hörn och pixelskuggare
Vi läser data från filen SimpleVertexShader.cso och tilldelar data till bytematrisen vertexShaderBytecode . Vi anropar ID3D11Enhet::CreateVertexShader med bytematrisen för att skapa hörnskuggningen (ID3D11VertexShader). Vi anger hörndjupvärdet till 0,5 i källan SimpleVertexShader.hlsl för att garantera att triangeln ritas. Vi fyller i en matris med D3D11_INPUT_ELEMENT_DESC strukturer för att beskriva layouten av vertex shader-koden och anropar sedan ID3D11Device::CreateInputLayout för att skapa layouten. Matrisen har ett layoutelement som definierar hörnpositionen. Vi läser data från filen SimplePixelShader.cso och tilldelar data till pixelShaderBytecode byte-matrisen. Vi anropar ID3D11Enhet::SkapaPixelShader med bytematrisen för att skapa pixelskuggningen (ID3D11PixelShader). Vi anger pixelvärdet till (1,1,1,1) i SimplePixelShader.hlsl-källan för att göra vår triangel gul. Du kan ändra färgen genom att ändra det här värdet.
Vi skapar hörn- och indexbuffertar som definierar en enkel triangel. För att göra detta definierar vi först triangeln, beskriver sedan hörn- och indexbuffertarna (D3D11_BUFFER_DESC och D3D11_SUBRESOURCE_DATA) med hjälp av triangeldefinitionen och anropar slutligen ID3D11Enhet::CreateBuffer en gång för varje buffert.
auto loadVSTask = DX::ReadDataAsync(L"SimpleVertexShader.cso");
auto loadPSTask = DX::ReadDataAsync(L"SimplePixelShader.cso");
// Load the raw vertex shader bytecode from disk and create a vertex shader with it.
auto createVSTask = loadVSTask.then([this](const std::vector<byte>& vertexShaderBytecode) {
ComPtr<ID3D11VertexShader> vertexShader;
DX::ThrowIfFailed(
m_d3dDevice->CreateVertexShader(
vertexShaderBytecode->Data,
vertexShaderBytecode->Length,
nullptr,
&vertexShader
)
);
// Create an input layout that matches the layout defined in the vertex shader code.
// For this lesson, this is simply a DirectX::XMFLOAT2 vector defining the vertex position.
const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
ComPtr<ID3D11InputLayout> inputLayout;
DX::ThrowIfFailed(
m_d3dDevice->CreateInputLayout(
basicVertexLayoutDesc,
ARRAYSIZE(basicVertexLayoutDesc),
vertexShaderBytecode->Data,
vertexShaderBytecode->Length,
&inputLayout
)
);
});
// Load the raw pixel shader bytecode from disk and create a pixel shader with it.
auto createPSTask = loadPSTask.then([this](const std::vector<byte>& pixelShaderBytecode) {
ComPtr<ID3D11PixelShader> pixelShader;
DX::ThrowIfFailed(
m_d3dDevice->CreatePixelShader(
pixelShaderBytecode->Data,
pixelShaderBytecode->Length,
nullptr,
&pixelShader
)
);
});
// Create vertex and index buffers that define a simple triangle.
auto createTriangleTask = (createPSTask && createVSTask).then([this] () {
DirectX::XMFLOAT2 triangleVertices[] =
{
float2(-0.5f, -0.5f),
float2( 0.0f, 0.5f),
float2( 0.5f, -0.5f),
};
unsigned short triangleIndices[] =
{
0, 1, 2,
};
D3D11_BUFFER_DESC vertexBufferDesc = {0};
vertexBufferDesc.ByteWidth = sizeof(float2) * ARRAYSIZE(triangleVertices);
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vertexBufferData;
vertexBufferData.pSysMem = triangleVertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
ComPtr<ID3D11Buffer> vertexBuffer;
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
&vertexBuffer
)
);
D3D11_BUFFER_DESC indexBufferDesc;
indexBufferDesc.ByteWidth = sizeof(unsigned short) * ARRAYSIZE(triangleIndices);
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA indexBufferData;
indexBufferData.pSysMem = triangleIndices;
indexBufferData.SysMemPitch = 0;
indexBufferData.SysMemSlicePitch = 0;
ComPtr<ID3D11Buffer> indexBuffer;
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&indexBufferDesc,
&indexBufferData,
&indexBuffer
)
);
});
Vi använder hörn- och pixelskuggarna, hörnskuggningslayouten och hörn- och indexbuffertarna för att rita en gul triangel.
4. Rita triangeln och presentera den renderade bilden
Vi går in i en oändlig loop för att kontinuerligt återge och visa scenen. Vi anropar ID3D11DeviceContext::OMSetRenderTargets för att ange återgivningsmålet som utdatamål. Vi anropar ID3D11DeviceContext::ClearRenderTargetView med { 0.071f, 0.04f, 0.561f, 1.0f } för att rensa återgivningsmålet till en helblå färg.
I den oändliga slingan ritar vi en gul triangel på den blå ytan.
Rita en gul triangel
- Först anropar vi ID3D11DeviceContext::IASetInputLayout för att beskriva hur hörnbuffertdata strömmas till indata-assembler-fasen.
- Därefter anropar vi ID3D11DeviceContext::IASetVertexBuffers och ID3D11DeviceContext::IASetIndexBuffer för att binda hörn- och indexbuffertar till indata-assembler-fasen.
- Därefter anropar vi ID3D11DeviceContext::IASetPrimitiveTopology med värdet D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP för att ange för indata-assembler-fasen för att tolka hörndata som en triangelremsa.
- Därefter anropar vi ID3D11DeviceContext::VSSetShader för att initiera hörnskuggningssteget med hörnskuggningskoden och ID3D11DeviceContext::P SSetShader för att initiera pixelskuggningssteget med pixelskuggningskoden.
- Slutligen anropar vi ID3D11DeviceContext::DrawIndexed för att rita triangeln och skicka den till renderingspipelinen.
Vi anropar IDXGISwapChain::Present för att presentera den renderade bilden i fönstret.
// Specify the render target we created as the output target.
m_d3dDeviceContext->OMSetRenderTargets(
1,
m_renderTargetView.GetAddressOf(),
nullptr // Use no depth stencil.
);
// Clear the render target to a solid color.
const float clearColor[4] = { 0.071f, 0.04f, 0.561f, 1.0f };
m_d3dDeviceContext->ClearRenderTargetView(
m_renderTargetView.Get(),
clearColor
);
m_d3dDeviceContext->IASetInputLayout(inputLayout.Get());
// Set the vertex and index buffers, and specify the way they define geometry.
UINT stride = sizeof(float2);
UINT offset = 0;
m_d3dDeviceContext->IASetVertexBuffers(
0,
1,
vertexBuffer.GetAddressOf(),
&stride,
&offset
);
m_d3dDeviceContext->IASetIndexBuffer(
indexBuffer.Get(),
DXGI_FORMAT_R16_UINT,
0
);
m_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Set the vertex and pixel shader stage state.
m_d3dDeviceContext->VSSetShader(
vertexShader.Get(),
nullptr,
0
);
m_d3dDeviceContext->PSSetShader(
pixelShader.Get(),
nullptr,
0
);
// Draw the cube.
m_d3dDeviceContext->DrawIndexed(
ARRAYSIZE(triangleIndices),
0,
0
);
// Present the rendered image to the window. Because the maximum frame latency is set to 1,
// the render loop will generally be throttled to the screen refresh rate, typically around
// 60 Hz, by sleeping the application on Present until the screen is refreshed.
DX::ThrowIfFailed(
m_swapChain->Present(1, 0)
);
Sammanfattning och nästa steg
Vi skapade och ritade en gul triangel med hjälp av hörn och pixelskuggor.
Därefter skapar vi en 3D-kub i omloppsbana och tillämpar belysningseffekter på den.
Använda djup och effekter på primitiver