• 07.深度


    介绍

    在本课程中,我们将通过创建深度/模板缓冲区和视图,然后将其绑定到OM舞台,学习如何隐含3D场景的深度。

    深度/模具视图

    深度/模板视图的作用是让管线的OM阶段检查渲染目标上所有像素细分的深度/模板值。像素片段是有可能被写入屏幕的像素。想想一个球体和一个盒子。球体位于框的后面,因此当它们通过渲染管线泵送时,来自球体的像素和来自框的像素都被放置到渲染目标上。这些像素称为像素片段。当像素到达OM阶段时,OM阶段会将像素片段深度值与该位置中已经存在的像素片段进行比较。如果新的像素片段深度值小于已经存在的像素片段,则将丢弃已经存在的像素片段,并将新的像素片段保留在渲染目标上。回到球体和盒子。假设先渲染球体。渲染目标上尚无几何图形,因此将渲染整个球体。但是,当盒子的像素到达OM阶段时,OM阶段会比较来自盒子的像素和来自球体的像素的深度值。由于框位于球体的前面,因此将丢弃球体的像素片段,并将框的像素片段保留在渲染目标上。绘制所有几何图形后,渲染目标上剩余的像素就是屏幕上显示的像素。由于框位于球体的前面,因此将丢弃球体的像素片段,并将框的像素片段保留在渲染目标上。绘制所有几何图形后,渲染目标上剩余的像素就是屏幕上显示的像素。由于框位于球体的前面,因此将丢弃球体的像素片段,并将框的像素片段保留在渲染目标上。绘制所有几何图形后,渲染目标上剩余的像素就是屏幕上显示的像素。 深度视图的模具部分用于高级技术,例如镜子,我们将在后面学习。

    全球宣言

    在这里,我们有两个新的接口对象。一种是存储深度/模板视图,另一种是存储深度/模板缓冲区。
    ID3D11DepthStencilView* depthStencilView;
    ID3D11Texture2D* depthStencilBuffer;
    

    深度/模板缓冲区说明

    现在转到初始化d3d的位置。在创建深度/模板缓冲区之前,我们需要对其进行定义。我们可以通过填充D3D11_TEXTURE2D_DESC来做到这一点,就像填充后台缓冲区一样。由于我们已经介绍了此结构,因此在这里真正需要提及的唯一一件事就是绑定标志和格式。格式为两个变量提供了空间;深度为24位,模板为8位。绑定标志表示此纹理将作为深度/模板缓冲区绑定到OM阶段。
    //Describe our Depth/Stencil Buffer
    D3D11_TEXTURE2D_DESC depthStencilDesc;
    
    depthStencilDesc.Width     = Width;
    depthStencilDesc.Height    = Height;
    depthStencilDesc.MipLevels = 1;
    depthStencilDesc.ArraySize = 1;
    depthStencilDesc.Format    = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilDesc.SampleDesc.Count   = 1;
    depthStencilDesc.SampleDesc.Quality = 0;
    depthStencilDesc.Usage          = D3D11_USAGE_DEFAULT;
    depthStencilDesc.BindFlags      = D3D11_BIND_DEPTH_STENCIL;
    depthStencilDesc.CPUAccessFlags = 0; 
    depthStencilDesc.MiscFlags      = 0;
    

    创建深度/模具视图

    现在我们已经定义了深度/模板缓冲区,我们需要创建它。我们可以使用设备接口的CreateTexture2D方法创建它。创建深度/模板缓冲区后,我们需要创建深度/模板视图,该视图将绑定到管道的OM阶段。我们通过从设备界面调用CreateDepthStencilView()来实现。第一个参数是我们的深度/模板缓冲区描述,第二个参数用于深度/模板状态。我们没有一个,因此将其设置为NULL。第三个是返回的深度/模板缓冲区。
    d3d11Device->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer);
    d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView);
    

    绑定深度/模具视图

    在程序中隐含深度的最后一件事是将其绑定到管道的OM阶段。还记得绑定渲染目标时使用的这个功能吗?在调用此函数并将第三个参数设置为NULL之前,因为我们没有深度/模具视图。现在我们有了一个,因此我们可以将该NULL参数更改为我们从上面创建的depthStencilView对象。
    d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, depthStencilView );
    

    向视口添加深度值

    转到我们创建和描述视口的位置。我们需要告诉流水线的OM阶段将像素的z值或深度值转换为0到1之间的值,其中0是最可能的值,而1是最远的值。
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    

    打扫干净

    不要忘记释放COM对象!
    depthStencilView->Release();
    depthStencilBuffer->Release();
    

    清除深度/模具视图

    我们需要确保做的最后一件事是清除每帧的深度/模板视图,就像我们对渲染目标视图所做的那样。我们通过调用设备上下文接口的ClearDepthStencilView()方法来实现。第一个值是我们要清除的深度/模板视图,第二个是枚举类型,或一起使用,指定要清除的深度/模板视图的一部分,第四个参数是我们要清除深度的值。我们将其设置为1.0f,因为1.0f是任何东西都可以拥有的最大深度值。这样可以确保在屏幕上绘制所有对象。如果我们在此处设置0.0f,则不会在屏幕上绘制任何东西,因为像素片段的所有深度值都将在0.0f和1.0f之间。最后一个参数是我们将模板设置为的值。由于未使用它,因此将其设置为0。
    d3d11DevCon->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
    


    不太难!

    行使:

    1.通过创建另一个z值小于我们平方的三角形来测试深度/模具视图。


    这是最终代码:

    main.cpp

    //Include and link appropriate libraries and headers//
    #pragma comment(lib, "d3d11.lib")
    #pragma comment(lib, "d3dx11.lib")
    #pragma comment(lib, "d3dx10.lib")
    
    #include <windows.h>
    #include <d3d11.h>
    #include <d3dx11.h>
    #include <d3dx10.h>
    #include <xnamath.h>
    
    //Global Declarations - Interfaces//
    IDXGISwapChain* SwapChain;
    ID3D11Device* d3d11Device;
    ID3D11DeviceContext* d3d11DevCon;
    ID3D11RenderTargetView* renderTargetView;
    ID3D11Buffer* squareIndexBuffer;
    ID3D11Buffer* squareVertBuffer;
    ///**************new**************
    ID3D11DepthStencilView* depthStencilView;
    ID3D11Texture2D* depthStencilBuffer;
    ///**************new**************
    ID3D11VertexShader* VS;
    ID3D11PixelShader* PS;
    ID3D10Blob* VS_Buffer;
    ID3D10Blob* PS_Buffer;
    ID3D11InputLayout* vertLayout;
    
    //Global Declarations - Others//
    LPCTSTR WndClassName = L"firstwindow";
    HWND hwnd = NULL;
    HRESULT hr;
    
    const int Width  = 300;
    const int Height = 300;
    
    //Function Prototypes//
    bool InitializeDirect3d11App(HINSTANCE hInstance);
    void CleanUp();
    bool InitScene();
    void UpdateScene();
    void DrawScene();
    
    bool InitializeWindow(HINSTANCE hInstance,
        int ShowWnd,
        int width, int height,
        bool windowed);
    int messageloop();
    
    LRESULT CALLBACK WndProc(HWND hWnd,
        UINT msg,
        WPARAM wParam,
        LPARAM lParam);
    
    //Vertex Structure and Vertex Layout (Input Layout)//
    struct Vertex    //Overloaded Vertex Structure
    {
        Vertex(){}
        Vertex(float x, float y, float z,
            float cr, float cg, float cb, float ca)
            : pos(x,y,z), color(cr, cg, cb, ca){}
    
        XMFLOAT3 pos;
        XMFLOAT4 color;
    };
    
    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },  
        { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },  
    };
    UINT numElements = ARRAYSIZE(layout);
    
    int WINAPI WinMain(HINSTANCE hInstance,    //Main windows function
        HINSTANCE hPrevInstance, 
        LPSTR lpCmdLine,
        int nShowCmd)
    {
    
        if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true))
        {
            MessageBox(0, L"Window Initialization - Failed",
                L"Error", MB_OK);
            return 0;
        }
    
        if(!InitializeDirect3d11App(hInstance))    //Initialize Direct3D
        {
            MessageBox(0, L"Direct3D Initialization - Failed",
                L"Error", MB_OK);
            return 0;
        }
    
        if(!InitScene())    //Initialize our scene
        {
            MessageBox(0, L"Scene Initialization - Failed",
                L"Error", MB_OK);
            return 0;
        }
    
        messageloop();
    
        CleanUp();    
    
        return 0;
    }
    
    bool InitializeWindow(HINSTANCE hInstance,
        int ShowWnd,
        int width, int height,
        bool windowed)
    {
        typedef struct _WNDCLASS {
            UINT cbSize;
            UINT style;
            WNDPROC lpfnWndProc;
            int cbClsExtra;
            int cbWndExtra;
            HANDLE hInstance;
            HICON hIcon;
            HCURSOR hCursor;
            HBRUSH hbrBackground;
            LPCTSTR lpszMenuName;
            LPCTSTR lpszClassName;
        } WNDCLASS;
    
        WNDCLASSEX wc;
    
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProc;
        wc.cbClsExtra = NULL;
        wc.cbWndExtra = NULL;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
        wc.lpszMenuName = NULL;
        wc.lpszClassName = WndClassName;
        wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    
        if (!RegisterClassEx(&wc))
        {
            MessageBox(NULL, L"Error registering class",    
                L"Error", MB_OK | MB_ICONERROR);
            return 1;
        }
    
        hwnd = CreateWindowEx(
            NULL,
            WndClassName,
            L"Lesson 4 - Begin Drawing",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT,
            width, height,
            NULL,
            NULL,
            hInstance,
            NULL
            );
    
        if (!hwnd)
        {
            MessageBox(NULL, L"Error creating window",
                L"Error", MB_OK | MB_ICONERROR);
            return 1;
        }
    
        ShowWindow(hwnd, ShowWnd);
        UpdateWindow(hwnd);
    
        return true;
    }
    
    bool InitializeDirect3d11App(HINSTANCE hInstance)
    {
        //Describe our SwapChain Buffer
        DXGI_MODE_DESC bufferDesc;
    
        ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
    
        bufferDesc.Width = Width;
        bufferDesc.Height = Height;
        bufferDesc.RefreshRate.Numerator = 60;
        bufferDesc.RefreshRate.Denominator = 1;
        bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
        bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    
        //Describe our SwapChain
        DXGI_SWAP_CHAIN_DESC swapChainDesc; 
    
        ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
    
        swapChainDesc.BufferDesc = bufferDesc;
        swapChainDesc.SampleDesc.Count = 1;
        swapChainDesc.SampleDesc.Quality = 0;
        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapChainDesc.BufferCount = 1;
        swapChainDesc.OutputWindow = hwnd; 
        swapChainDesc.Windowed = TRUE; 
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    
    
        //Create our SwapChain
        hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
            D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
    
        //Create our BackBuffer
        ID3D11Texture2D* BackBuffer;
        hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
    
        //Create our Render Target
        hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
        BackBuffer->Release();
    
        ///**************new**************
        //Describe our Depth/Stencil Buffer
        D3D11_TEXTURE2D_DESC depthStencilDesc;
    
        depthStencilDesc.Width     = Width;
        depthStencilDesc.Height    = Height;
        depthStencilDesc.MipLevels = 1;
        depthStencilDesc.ArraySize = 1;
        depthStencilDesc.Format    = DXGI_FORMAT_D24_UNORM_S8_UINT;
        depthStencilDesc.SampleDesc.Count   = 1;
        depthStencilDesc.SampleDesc.Quality = 0;
        depthStencilDesc.Usage          = D3D11_USAGE_DEFAULT;
        depthStencilDesc.BindFlags      = D3D11_BIND_DEPTH_STENCIL;
        depthStencilDesc.CPUAccessFlags = 0; 
        depthStencilDesc.MiscFlags      = 0;
    
        //Create the Depth/Stencil View
        d3d11Device->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer);
        d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView);
    
        //Set our Render Target
        d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, depthStencilView );
        ///**************new**************
    
        return true;
    }
    
    void CleanUp()
    {
        //Release the COM Objects we created
        SwapChain->Release();
        d3d11Device->Release();
        d3d11DevCon->Release();
        renderTargetView->Release();
        squareVertBuffer->Release();
        squareIndexBuffer->Release();
        VS->Release();
        PS->Release();
        VS_Buffer->Release();
        PS_Buffer->Release();
        vertLayout->Release();
        ///**************new**************
        depthStencilView->Release();
        depthStencilBuffer->Release();
        ///**************new**************
    }
    
    bool InitScene()
    {
        //Compile Shaders from shader file
        hr = D3DX11CompileFromFile(L"Effects.fx", 0, 0, "VS", "vs_4_0", 0, 0, 0, &VS_Buffer, 0, 0);
        hr = D3DX11CompileFromFile(L"Effects.fx", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS_Buffer, 0, 0);
    
        //Create the Shader Objects
        hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);
        hr = d3d11Device->CreatePixelShader(PS_Buffer->GetBufferPointer(), PS_Buffer->GetBufferSize(), NULL, &PS);
    
        //Set Vertex and Pixel Shaders
        d3d11DevCon->VSSetShader(VS, 0, 0);
        d3d11DevCon->PSSetShader(PS, 0, 0);
    
        //Create the vertex buffer
        Vertex v[] =
        {
            Vertex( -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f ),
            Vertex( -0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f ),
            Vertex(  0.5f,  0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f ),
            Vertex(  0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f ),
        };
    
        DWORD indices[] = {
            0, 1, 2,
            0, 2, 3,
        };
    
        D3D11_BUFFER_DESC indexBufferDesc;
        ZeroMemory( &indexBufferDesc, sizeof(indexBufferDesc) );
    
        indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
        indexBufferDesc.ByteWidth = sizeof(DWORD) * 2 * 3;
        indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
        indexBufferDesc.CPUAccessFlags = 0;
        indexBufferDesc.MiscFlags = 0;
    
        D3D11_SUBRESOURCE_DATA iinitData;
    
        iinitData.pSysMem = indices;
        d3d11Device->CreateBuffer(&indexBufferDesc, &iinitData, &squareIndexBuffer);
    
        d3d11DevCon->IASetIndexBuffer( squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
    
    
        D3D11_BUFFER_DESC vertexBufferDesc;
        ZeroMemory( &vertexBufferDesc, sizeof(vertexBufferDesc) );
    
        vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
        vertexBufferDesc.ByteWidth = sizeof( Vertex ) * 4;
        vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
        vertexBufferDesc.CPUAccessFlags = 0;
        vertexBufferDesc.MiscFlags = 0;
    
        D3D11_SUBRESOURCE_DATA vertexBufferData; 
    
        ZeroMemory( &vertexBufferData, sizeof(vertexBufferData) );
        vertexBufferData.pSysMem = v;
        hr = d3d11Device->CreateBuffer( &vertexBufferDesc, &vertexBufferData, &squareVertBuffer);
    
        //Set the vertex buffer
        UINT stride = sizeof( Vertex );
        UINT offset = 0;
        d3d11DevCon->IASetVertexBuffers( 0, 1, &squareVertBuffer, &stride, &offset );
    
        //Create the Input Layout
        hr = d3d11Device->CreateInputLayout( layout, numElements, VS_Buffer->GetBufferPointer(), 
            VS_Buffer->GetBufferSize(), &vertLayout );
    
        //Set the Input Layout
        d3d11DevCon->IASetInputLayout( vertLayout );
    
        //Set Primitive Topology
        d3d11DevCon->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
    
        //Create the Viewport
        D3D11_VIEWPORT viewport;
        ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
    
        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;
        viewport.Width = Width;
        viewport.Height = Height;
        ///**************new**************
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 1.0f;
        ///**************new**************
    
        //Set the Viewport
        d3d11DevCon->RSSetViewports(1, &viewport);
    
        return true;
    }
    
    void UpdateScene()
    {
    
    }
    
    void DrawScene()
    {
        //Clear our backbuffer
        float bgColor[4] = {(0.0f, 0.0f, 0.0f, 0.0f)};
        d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);
    
        ///**************new**************
        //Refresh the Depth/Stencil view
        d3d11DevCon->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
        ///**************new**************
    
        //Draw the triangle
        d3d11DevCon->DrawIndexed( 6, 0, 0 );
    
        //Present the backbuffer to the screen
        SwapChain->Present(0, 0);
    }
    
    int messageloop(){
        MSG msg;
        ZeroMemory(&msg, sizeof(MSG));
        while(true)
        {
            BOOL PeekMessageL( 
                LPMSG lpMsg,
                HWND hWnd,
                UINT wMsgFilterMin,
                UINT wMsgFilterMax,
                UINT wRemoveMsg
                );
    
            if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                if (msg.message == WM_QUIT)
                    break;
                TranslateMessage(&msg);    
                DispatchMessage(&msg);
            }
            else{
                // run game code            
                UpdateScene();
                DrawScene();
            }
        }
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd,
        UINT msg,
        WPARAM wParam,
        LPARAM lParam)
    {
        switch( msg )
        {
        case WM_KEYDOWN:
            if( wParam == VK_ESCAPE ){
                DestroyWindow(hwnd);
            }
            return 0;
    
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd,
            msg,
            wParam,
            lParam);
    }
    


    Effects.fx:

    struct VS_OUTPUT
    {
        float4 Pos : SV_POSITION;
        float4 Color : COLOR;
    };
    
    VS_OUTPUT VS(float4 inPos : POSITION, float4 inColor : COLOR)
    {
        VS_OUTPUT output;
    
        output.Pos = inPos;
        output.Color = inColor;
    
        return output;
    }
    
    float4 PS(VS_OUTPUT input) : SV_TARGET
    {
        return input.Color;
    }
    
  • 相关阅读:
    神经网络的数学推导
    矩阵乘法的梯度计算
    深入理解设计矩阵(Design Matrix)
    拉格朗日乘子
    PRML中文版(马春鹏)勘误表
    增强学习笔记 第三章 马尔科夫决策过程
    贝叶斯统计推断的阅读笔记
    Kalman Filter的数学推导
    线性代数随笔(二):矩阵和向量乘法
    线性代数随笔(一):线性变换,特征分解,二次型
  • 原文地址:https://www.cnblogs.com/szmtjs10/p/16110356.html
Copyright © 2020-2023  润新知