C++ Can';无法从Direct3D获取抗锯齿图片

C++ Can';无法从Direct3D获取抗锯齿图片,c++,directx,direct3d,game-development,C++,Directx,Direct3d,Game Development,我正在使用Direct3D进行编程的第一步。我有一个非常基本的管道设置,我只想从中得到一个抗锯齿平滑图像。但我明白了: 首先,尽管我的管道中已经启用了4x MSAA(DXGI_SAMPLE_DESC::Count为4,Quality为0),但我无法摆脱楼梯效果: 第二,我得到了这种嘈杂的纹理,虽然我已经生成了mipmap,并且在sampler状态下设置了线性过滤。 我是错过了什么还是做错了 这是我的密码: 1) 渲染器类: #include "Scene.h" // Custom clas

我正在使用Direct3D进行编程的第一步。我有一个非常基本的管道设置,我只想从中得到一个抗锯齿平滑图像。但我明白了:

首先,尽管我的管道中已经启用了4x MSAA(DXGI_SAMPLE_DESC::Count为4,Quality为0),但我无法摆脱楼梯效果:

第二,我得到了这种嘈杂的纹理,虽然我已经生成了mipmap,并且在sampler状态下设置了线性过滤。

我是错过了什么还是做错了

这是我的密码:

1) 渲染器类:

#include "Scene.h" // Custom class that contains vertex and index buffer contents for every rendered mesh.
#include "Camera.h" // Custom class that contains camera position and fov.

#include <wrl/client.h>
using Microsoft::WRL::ComPtr;

#include <DirectXMath.h>
using namespace DirectX;

#include <map>

#include "generated\VertexShader.h"
#include "generated\PixelShader.h"

class Renderer
{
public:
    Renderer(HWND hWnd, int wndWidth, int wndHeight, const Scene& scene, const Camera& camera);

    void Render();

    void SwitchToWireframe();
    void SwitchToSolid();

protected:
    void CreateDeviceAndSwapChain();
    void CreateDepthStencil();
    void CreateInputLayout();
    void CreateVertexShader();
    void CreatePixelShader();
    void CreateRasterizerStates();
    void CreateBlendState();
    void CreateSamplerState();
    void CreateBuffer(ID3D11Buffer** buffer, 
        D3D11_USAGE usage, D3D11_BIND_FLAG bindFlags,
        UINT cpuAccessFlags, UINT miscFlags,
        UINT sizeOfBuffer, UINT sizeOfBufferElement, const void* initialData);
    void CreateTexture2DAndSRV(const Scene::Texture& texture, ID3D11ShaderResourceView** view);
    void CreateTexturesAndViews();
    void GenerateMips();

protected:
    const Scene& m_scene;

    const Camera& m_camera;
    DWORD m_cameraLastUpdateTickCount;

    HWND m_windowHandle;
    int m_windowWidth; 
    int m_windowHeight;

    DXGI_SAMPLE_DESC m_sampleDesc;

    ComPtr<IDXGISwapChain> m_swapChain;
    ComPtr<ID3D11Texture2D> m_swapChainBuffer;
    ComPtr<ID3D11RenderTargetView> m_swapChainBufferRTV;
    ComPtr<ID3D11Device> m_device;
    ComPtr<ID3D11DeviceContext> m_deviceContext;
    ComPtr<ID3D11Debug> m_debugger;
    ComPtr<ID3D11Texture2D> m_depthStencilTexture;
    ComPtr<ID3D11DepthStencilState> m_depthStencilState;
    ComPtr<ID3D11DepthStencilView> m_depthStencilView;
    ComPtr<ID3D11InputLayout> m_inputLayout;
    ComPtr<ID3D11VertexShader> m_vertexShader;
    ComPtr<ID3D11PixelShader> m_pixelShader;
    ComPtr<ID3D11RasterizerState> m_solidRasterizerState;
    ComPtr<ID3D11RasterizerState> m_wireframeRasterizerState;
    ComPtr<ID3D11BlendState> m_blendState;
    ComPtr<ID3D11SamplerState> m_linearSamplerState;

    std::map<std::string, ComPtr<ID3D11ShaderResourceView>> m_diffuseMapViews;
    std::map<std::string, ComPtr<ID3D11ShaderResourceView>> m_normalMapViews;

    XMMATRIX m_worldViewMatrix;

    ID3D11RasterizerState* m_currentRasterizerState;
};

void Renderer::CreateDeviceAndSwapChain()
{
    HRESULT hr;

    DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
    swapChainDesc.BufferDesc.Width = m_windowWidth;
    swapChainDesc.BufferDesc.Height = m_windowHeight;
    swapChainDesc.BufferDesc.RefreshRate.Numerator = 1;
    swapChainDesc.BufferDesc.RefreshRate.Denominator = 60;
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
    swapChainDesc.SampleDesc = m_sampleDesc;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.BufferCount = 1;
    swapChainDesc.OutputWindow = m_windowHandle;
    swapChainDesc.Windowed = TRUE;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    D3D_FEATURE_LEVEL desiredFeatureLevels[] = { D3D_FEATURE_LEVEL_10_1 };
    D3D_FEATURE_LEVEL featureLevel;

    hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
        D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
        desiredFeatureLevels, 1, D3D11_SDK_VERSION, &swapChainDesc,
        m_swapChain.GetAddressOf(), m_device.GetAddressOf(), &featureLevel, 
        m_deviceContext.GetAddressOf());

    if (FAILED(hr))
    {
        hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL,
            D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
            desiredFeatureLevels, 1, D3D11_SDK_VERSION, &swapChainDesc,
            m_swapChain.GetAddressOf(), m_device.GetAddressOf(), &featureLevel,
            m_deviceContext.GetAddressOf());
    }

    if (FAILED(hr))
        throw std::exception("Failed to create device or swap chain");

    hr = m_device->QueryInterface(m_debugger.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to get debugger interface");

    hr = m_swapChain->GetBuffer(0, __uuidof(m_swapChainBuffer),
        (void**)m_swapChainBuffer.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to get swap chain buffer");

    hr = m_device->CreateRenderTargetView(m_swapChainBuffer.Get(), NULL, 
        m_swapChainBufferRTV.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create RTV for swap chain buffer");
}

void Renderer::CreateDepthStencil()
{
    HRESULT hr;

    D3D11_TEXTURE2D_DESC tdesc;
    tdesc.Width = m_windowWidth;
    tdesc.Height = m_windowHeight;
    tdesc.MipLevels = 1;
    tdesc.ArraySize = 1;
    tdesc.Format = DXGI_FORMAT_D16_UNORM;
    tdesc.SampleDesc = m_sampleDesc;
    tdesc.Usage = D3D11_USAGE_DEFAULT;
    tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    tdesc.CPUAccessFlags = 0;
    tdesc.MiscFlags = 0;

    hr = m_device->CreateTexture2D(&tdesc, NULL, m_depthStencilTexture.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create depth stencil texture");

    D3D11_DEPTH_STENCIL_VIEW_DESC dsvdesc;
    dsvdesc.Format = DXGI_FORMAT_D16_UNORM;
    dsvdesc.ViewDimension = m_sampleDesc.Count > 1 
        ? D3D11_DSV_DIMENSION_TEXTURE2DMS 
        : D3D11_DSV_DIMENSION_TEXTURE2D;
    dsvdesc.Flags = 0;
    dsvdesc.Texture2D.MipSlice = 0;

    hr = m_device->CreateDepthStencilView(m_depthStencilTexture.Get(), &dsvdesc, 
        m_depthStencilView.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create depth stencil view");

    D3D11_DEPTH_STENCIL_DESC dsdesc;
    dsdesc.DepthEnable = TRUE;
    dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    dsdesc.DepthFunc = D3D11_COMPARISON_LESS;
    dsdesc.StencilEnable = FALSE;
    dsdesc.StencilReadMask = 0;
    dsdesc.StencilWriteMask = 0;
    dsdesc.FrontFace = {};
    dsdesc.BackFace = {};

    hr = m_device->CreateDepthStencilState(&dsdesc, m_depthStencilState.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create depth stencil state");
}

void Renderer::CreateInputLayout()
{
    HRESULT hr;

    D3D11_INPUT_ELEMENT_DESC iedescs[] = {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };

    hr = m_device->CreateInputLayout(iedescs, 3,
        g_vertexShader, sizeof(g_vertexShader),
        m_inputLayout.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create input layout");
}

void Renderer::CreateVertexShader()
{
    HRESULT hr;

    hr = m_device->CreateVertexShader(g_vertexShader, sizeof(g_vertexShader), 
        NULL, m_vertexShader.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create vertex shader");
}

void Renderer::CreatePixelShader()
{
    HRESULT hr;

    hr = m_device->CreatePixelShader(g_pixelShader, sizeof(g_pixelShader), 
        NULL, m_pixelShader.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create pixel shader");
}

void Renderer::CreateRasterizerStates()
{
    HRESULT hr;

    D3D11_RASTERIZER_DESC rdesc;
    rdesc.FillMode = D3D11_FILL_SOLID;
    rdesc.CullMode = D3D11_CULL_FRONT;
    rdesc.FrontCounterClockwise = FALSE;
    rdesc.DepthBias = 0;
    rdesc.DepthBiasClamp = 0.0f;
    rdesc.SlopeScaledDepthBias = 0.0f;
    rdesc.DepthClipEnable = TRUE;
    rdesc.ScissorEnable = FALSE;
    rdesc.MultisampleEnable = m_sampleDesc.Count > 1 ? TRUE : FALSE;
    rdesc.AntialiasedLineEnable = m_sampleDesc.Count > 1 ? TRUE : FALSE;

    hr = m_device->CreateRasterizerState(&rdesc, m_solidRasterizerState.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create rasterizer state");

    rdesc.FillMode = D3D11_FILL_WIREFRAME;

    hr = m_device->CreateRasterizerState(&rdesc, m_wireframeRasterizerState.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create rasterizer state");

    m_currentRasterizerState = m_solidRasterizerState.Get();
}

void Renderer::CreateSamplerState()
{
    HRESULT hr;

    D3D11_SAMPLER_DESC smdesc;
    smdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    smdesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    smdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    smdesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    smdesc.MipLODBias = 0.0f;
    smdesc.MaxAnisotropy = 0;
    smdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
    smdesc.BorderColor[4] = {};
    FLOAT MinLOD = 0.0;
    FLOAT MaxLOD = 0.0;

    hr = m_device->CreateSamplerState(&smdesc, m_linearSamplerState.GetAddressOf());

    if (FAILED(hr))
        throw new std::exception("Failed to create sampler state");
}

void Renderer::CreateBlendState()
{
    HRESULT hr;

    D3D11_BLEND_DESC bdesc;
    bdesc.AlphaToCoverageEnable = FALSE;
    bdesc.IndependentBlendEnable = FALSE;
    bdesc.RenderTarget[0].BlendEnable = FALSE;
    bdesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
    bdesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
    bdesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    bdesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
    bdesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

    hr = m_device->CreateBlendState(&bdesc, m_blendState.GetAddressOf());

    if (FAILED(hr))
        throw std::exception("Failed to create blend state");
}

 void Renderer::CreateBuffer(ID3D11Buffer** buffer, 
     D3D11_USAGE usage, D3D11_BIND_FLAG bindFlags,
    UINT cpuAccessFlags, UINT miscFlags, 
    UINT sizeOfBuffer, UINT sizeOfBufferElement, const void* initialData)
{
    HRESULT hr;

    D3D11_BUFFER_DESC bdesc;
    bdesc.ByteWidth = sizeOfBuffer;
    bdesc.Usage = usage;
    bdesc.BindFlags = bindFlags;
    bdesc.CPUAccessFlags = cpuAccessFlags;
    bdesc.MiscFlags = miscFlags;
    bdesc.StructureByteStride = sizeOfBufferElement;

    D3D11_SUBRESOURCE_DATA bdata;
    bdata.pSysMem = initialData;
    bdata.SysMemPitch = 0;
    bdata.SysMemSlicePitch = 0;

    hr = m_device->CreateBuffer(&bdesc, &bdata, buffer);

    if (FAILED(hr))
        throw std::exception("Failed to create buffer");
}

 void Renderer::CreateTexture2DAndSRV(const Scene::Texture& sceneTexture, ID3D11ShaderResourceView** view)
 {
     HRESULT hr;

     constexpr DXGI_FORMAT texformat = DXGI_FORMAT_R32G32B32A32_FLOAT;

     D3D11_TEXTURE2D_DESC tdesc;
     tdesc.Width = sceneTexture.width;
     tdesc.Height = sceneTexture.height;
     tdesc.MipLevels = 0;
     tdesc.ArraySize = 1;
     tdesc.Format = texformat;
     tdesc.SampleDesc.Count = 1;
     tdesc.SampleDesc.Quality = 0;
     tdesc.Usage = D3D11_USAGE_DEFAULT;
     tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
     tdesc.CPUAccessFlags = 0;
     tdesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;

     ComPtr<ID3D11Texture2D> texture2d;

     hr = m_device->CreateTexture2D(&tdesc, NULL, texture2d.GetAddressOf());

     if (FAILED(hr))
         throw std::exception("Failed to create texture");


     D3D11_SUBRESOURCE_DATA srdata;
     srdata.pSysMem = sceneTexture.data;
     srdata.SysMemPitch = sceneTexture.width * sizeof(float) * 4;
     srdata.SysMemSlicePitch = 0;

     m_deviceContext->UpdateSubresource(texture2d.Get(), 0, NULL, 
         srdata.pSysMem, srdata.SysMemPitch, srdata.SysMemSlicePitch);


     D3D11_SHADER_RESOURCE_VIEW_DESC srvdesc;
     srvdesc.Format = texformat;
     srvdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
     srvdesc.Texture2D.MostDetailedMip = 0;
     srvdesc.Texture2D.MipLevels = -1;

     ComPtr<ID3D11ShaderResourceView> shaderResourceView;

     hr = m_device->CreateShaderResourceView(texture2d.Get(), &srvdesc, view);

     if (FAILED(hr))
         throw std::exception("Failed to create shader resource view");
 }

 void Renderer::CreateTexturesAndViews()
 {
     for (auto it = m_scene.materials.cbegin(); it != m_scene.materials.cend(); it++)
     {
         //don't know what's the problem but if I don't place initialized ComPtr<...> instance into a map
         //then further .GetAddessOf() fails.
         m_diffuseMapViews.emplace(it->first, ComPtr<ID3D11ShaderResourceView>());
         m_normalMapViews.emplace(it->first, ComPtr<ID3D11ShaderResourceView>()); 

         CreateTexture2DAndSRV(it->second.diffuseMap, m_diffuseMapViews[it->first].GetAddressOf());
         CreateTexture2DAndSRV(it->second.normalMap, m_normalMapViews[it->first].GetAddressOf());
     }
 }

 void Renderer::GenerateMips()
 {
     for (auto it = m_diffuseMapViews.begin(); it != m_diffuseMapViews.end(); it++)
         m_deviceContext->GenerateMips(it->second.Get());
     for (auto it = m_normalMapViews.begin(); it != m_normalMapViews.end(); it++)
         m_deviceContext->GenerateMips(it->second.Get());
 }

Renderer::Renderer(HWND hWnd, int windowWidth, int windowHeight, 
    const Scene& scene, const Camera& camera)
    : m_scene(scene)
    , m_camera(camera)
    , m_cameraLastUpdateTickCount(0)
    , m_windowHandle(hWnd)
    , m_windowWidth(windowWidth)
    , m_windowHeight(windowHeight)
{
    m_sampleDesc.Count = 4;
    m_sampleDesc.Quality = 0;

    CreateDeviceAndSwapChain();
    CreateDepthStencil();
    CreateInputLayout();
    CreateVertexShader();
    CreatePixelShader();
    CreateRasterizerStates();
    CreateBlendState();
    CreateSamplerState();
    CreateTexturesAndViews();
    GenerateMips();

    // Setting up IA stage

    m_deviceContext->IASetPrimitiveTopology(
        D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    m_deviceContext->IASetInputLayout(m_inputLayout.Get());

    // Setting up VS stage

    m_deviceContext->VSSetShader(m_vertexShader.Get(), 0, 0);

    // Setting up RS stage

    D3D11_VIEWPORT viewport;
    viewport.TopLeftX = 0.0f;
    viewport.TopLeftY = 0.0f;
    viewport.Width = static_cast<FLOAT>(m_windowWidth);
    viewport.Height = static_cast<FLOAT>(m_windowHeight);
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;

    m_deviceContext->RSSetViewports(1, &viewport);

    // Setting up PS stage

    m_deviceContext->PSSetSamplers(0, 1, m_linearSamplerState.GetAddressOf());
    m_deviceContext->PSSetShader(m_pixelShader.Get(), 0, 0);

    // Setting up OM stage

    m_deviceContext->OMSetBlendState(m_blendState.Get(), NULL, 0xffffffff);
    m_deviceContext->OMSetDepthStencilState(m_depthStencilState.Get(), 0);
    m_deviceContext->OMSetRenderTargets(1, m_swapChainBufferRTV.GetAddressOf(), m_depthStencilView.Get());
}

void Renderer::Render()
{
    constexpr float background[4] = { 0.047f, 0.0487f, 0.066f, 1.0f };

    // Setting up view matix

    if (m_cameraLastUpdateTickCount
        != m_camera.GetLastUpdateTickCount())
    {
        const Float3& camFrom = m_camera.GetFrom();
        const Float3& camAt = m_camera.GetAt();
        const Float3& camUp = m_camera.GetUp();

        m_cameraLastUpdateTickCount = m_camera.GetLastUpdateTickCount();

        FXMVECTOR from = XMVectorSet(camFrom.x, camFrom.y, camFrom.z, 1.0f);
        FXMVECTOR at = XMVectorSet(camAt.x, camAt.y, camAt.z, 1.0f);
        FXMVECTOR up = XMVectorSet(camUp.x, camUp.y, camUp.z, 0.0f);

        FXMVECTOR dir = XMVectorSubtract(at, from);

        FXMVECTOR x = XMVector3Cross(dir, up);
        FXMVECTOR up2 = XMVector3Cross(x, dir);

        XMMATRIX lookTo = XMMatrixLookToRH(from, dir, up2);

        float scalef = 1.0f / XMVectorGetByIndex(XMVector3Length(dir), 0);

        XMMATRIX scale = XMMatrixScaling(scalef, scalef, scalef);

        float aspect = float(m_windowWidth) / m_windowHeight;
        float fov = m_camera.GetFov() / 180.0f * 3.14f;

        XMMATRIX persp = XMMatrixPerspectiveFovRH(fov, aspect, 0.1f, 1000.0f);

        m_worldViewMatrix = XMMatrixMultiply(XMMatrixMultiply(lookTo, scale), persp);
    }
    else
    {
        return;
    }

    m_deviceContext->ClearDepthStencilView(m_depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
    m_deviceContext->ClearRenderTargetView(m_swapChainBufferRTV.Get(), background);

    for (auto imesh = m_scene.meshes.cbegin(); imesh != m_scene.meshes.cend(); imesh++)
    {
        // Creating vertex buffer

        ComPtr<ID3D11Buffer> vertexBuffer;

        CreateBuffer(vertexBuffer.GetAddressOf(), 
            D3D11_USAGE_DEFAULT, D3D11_BIND_VERTEX_BUFFER, 0, 0,
            sizeof(Scene::Vertex) * imesh->vertices.size(), sizeof(Scene::Vertex),
            imesh->vertices.data());

        // Creating index buffer

        ComPtr<ID3D11Buffer> indexBuffer;

        CreateBuffer(indexBuffer.GetAddressOf(),
            D3D11_USAGE_DEFAULT, D3D11_BIND_INDEX_BUFFER, 0, 0,
            sizeof(unsigned int) * imesh->indices.size(), sizeof(unsigned int),
            imesh->indices.data());

        // Creating constant buffer

        ComPtr<ID3D11Buffer> constantBuffer;

        CreateBuffer(constantBuffer.GetAddressOf(),
            D3D11_USAGE_IMMUTABLE, D3D11_BIND_CONSTANT_BUFFER, 0, 0,
            sizeof(XMMATRIX), sizeof(XMMATRIX),
            &m_worldViewMatrix);

        // Setting up IA stage

        ID3D11Buffer* vertexBuffers[8] = { vertexBuffer.Get() };
        unsigned int vertexBufferStrides[8] = { sizeof(Scene::Vertex) };
        unsigned int vertexBufferOffsets[8] = { 0 };

        m_deviceContext->IASetVertexBuffers(0, 8,
            vertexBuffers, vertexBufferStrides, vertexBufferOffsets);

        m_deviceContext->IASetIndexBuffer(indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);

        // Setting up VS stage

        m_deviceContext->VSSetConstantBuffers(0, 1, constantBuffer.GetAddressOf());

        // Setting up RS stage

        m_deviceContext->RSSetState(m_currentRasterizerState);

        // Setting up PS stage

        ID3D11ShaderResourceView* srvs[2] = { };
        srvs[0] = m_diffuseMapViews.at(imesh->material).Get();
        srvs[1] = m_normalMapViews.at(imesh->material).Get();

        m_deviceContext->PSSetShaderResources(0, 2, srvs);

        // Drawing

        m_deviceContext->DrawIndexed(imesh->indices.size(), 0, 0);
    }

    m_swapChain->Present(0, 0);
}

void Renderer::SwitchToWireframe()
{
    m_currentRasterizerState = m_wireframeRasterizerState.Get();
    m_camera.UpdateLastUpdateTickCount();
}

void Renderer::SwitchToSolid()
{
    m_currentRasterizerState = m_solidRasterizerState.Get();
    m_camera.UpdateLastUpdateTickCount();
}
3) 像素着色器

Texture2D DiffuseMap : register(t0);
Texture2D NormalMap: register(t1);

SamplerState LinearSampler : register(s0);

float4 main(VS_OUTPUT input) : SV_TARGET
{
    float3 light = normalize(float3(2.87, -0.36, 1.68));

    float3 diffuseColor = DiffuseMap.Sample(LinearSampler, input.texcoord);
    float3 normalDisplace = float3(0.0, 0.0, 1.0) - NormalMap.Sample(LinearSampler, input.texcoord);

    float illumination = clamp(dot(light, input.normal + normalDisplace), 0.2, 1.0);

    return float4(mul(diffuseColor, illumination), 1.0);
}

好吧,我刚刚找出了楼梯效应的原因:

原因是我为CreateWindow WinApi函数和DXGI_SWAP_CHAIN_DESC::BufferDesc传递了相同的宽度和高度值。同时,这些应该是不同的,因为CreateWindow需要创建窗口的外部宽度和高度(窗口矩形),而BufferDesc应该接收内部值(窗口客户端区域矩形)。因为屏幕上的实际区域比交换链缓冲区小,渲染结果可能被重新采样以适合矩形,这在应用MSAA后引入了锯齿

解决此问题可获得更为清晰的结果(此处应用了4x MSAA):

但纹理锯齿的问题仍然悬而未决:

Texture2D DiffuseMap : register(t0);
Texture2D NormalMap: register(t1);

SamplerState LinearSampler : register(s0);

float4 main(VS_OUTPUT input) : SV_TARGET
{
    float3 light = normalize(float3(2.87, -0.36, 1.68));

    float3 diffuseColor = DiffuseMap.Sample(LinearSampler, input.texcoord);
    float3 normalDisplace = float3(0.0, 0.0, 1.0) - NormalMap.Sample(LinearSampler, input.texcoord);

    float illumination = clamp(dot(light, input.normal + normalDisplace), 0.2, 1.0);

    return float4(mul(diffuseColor, illumination), 1.0);
}