HLSL的问题渲染到纹理

时间:2017-02-09 01:33:16

标签: directx-11 hlsl render-to-texture

问题: 如何通过返回带有语义映射的结构来通过HLSL进行目标渲染?

你好。我是DirectX11的新手,我正在尝试设置渲染到纹理,所以我可以实现延迟着色。我花了一天时间在网上寻找解决问题的办法,但到目前为止还没有运气。

目前,我可以通过HLSL将场景渲染为单个纹理,然后通过将该纹理渲染为全屏四边形而不会出现问题。但是,如果我绑定多个渲染目标,我所看到的只是目标的清晰颜色,像素着色器似乎永远不会达到任何绑定纹理。我在运行时设置了D3D11_CREATE_DEVICE_DEBUG没有警告/错误,我尝试使用Visual Studio 2013图形调试工具,但我很难理解问题所在。这可能是相关的源代码:

着色器代码:(使用vs_5_0编译,ps_5_0)

// vertex shader
cbuffer mTransformationBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

struct VertexInputType
{
    float4 position : POSITION;
    float4 color    : COLOR;
    float3 normal   : NORMAL;
};
struct PixelInputType
{
    float4 position : SV_POSITION;
    float4 color    : COLOR;
    float3 normal   : NORMAL;
};
// this does not seem to work!
struct PixelOutputType
{
    float4 position : SV_TARGET0;
    float4 normal   : SV_TARGET1;
};


PixelInputType VertexEntry(VertexInputType input)
{
    input.position.w = 1.0f;

    PixelInputType output;
    output.position = mul(input.position, worldMatrix);
    output.normal = mul(input.normal, (float3x3)worldMatrix);
    output.normal = normalize(output.normal);

    output.color = input.color;

    return output;
}

// fragment shader
PixelOutputType FragmentEntry(PixelInputType input)
{
    PixelOutputType output;

    // render as white so I can see MRT working
    output.position = float4(1.0f, 1.0f, 1.0f, 1.0f);
    output.normal = float4(1.0f, 1.0f, 1.0f, 1.0f);

    return output;
}

渲染目标创建:

void RenderTargetManager::createTarget(const std::string& name, unsigned int width, unsigned int height, DXGI_FORMAT format)
{
unsigned int hash = hashString(name);

RenderTarget target;

// create the texture to render to
target.mTexture = TextureUtils::createTexture2d(mDevice, width, height, format, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);

// create the render target view
D3D11_RENDER_TARGET_VIEW_DESC rtViewDesc;
memset(&rtViewDesc, 0, sizeof(rtViewDesc));

rtViewDesc.Format = format;
rtViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;

HRESULT ret = S_OK;
ret = mDevice.CreateRenderTargetView(target.mTexture, &rtViewDesc, &target.mRenderTargetView);
ASSERT(ret == S_OK, "Failed to create a render target view.");

// create the shader resource view
D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
memset(&srViewDesc, 0, sizeof(srViewDesc));

srViewDesc.Format = format;
srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srViewDesc.Texture2D.MipLevels = 1;

ret = mDevice.CreateShaderResourceView(target.mTexture, &srViewDesc, &target.mShaderResourceView);
ASSERT(ret == S_OK, "Failed to create a shader resource view.");

mRenderTargetMap[hash] = target;
}

设置渲染目标:

void RenderTargetManager::setTargets(ID3D11DepthStencilView* depthStencilView, unsigned int numTargets, ...)
{
    va_list args;
    va_start(args, numTargets);

    std::vector<ID3D11RenderTargetView*> renderTargetViews;

    for (unsigned int i = 0; i < numTargets; ++i)
    {
        std::string renderTargetName = va_arg(args, char*);
        unsigned int hash = hashString(renderTargetName);

        auto it = mRenderTargetMap.find(hash);
        if (it != mRenderTargetMap.end())
        {
            renderTargetViews.push_back(it->second.mRenderTargetView);
        }
        else
        {
            LOGW("Render target view '%s' not found.", renderTargetName.c_str());
        }
    }

    va_end(args);

    if (!renderTargetViews.empty())
    {
        ASSERT(renderTargetViews.size() == numTargets, "Failed to set render targets. Not all targets found.");
        mDeviceContext.OMSetRenderTargets(renderTargetViews.size(), &renderTargetViews[0], depthStencilView);
    }
}

我的像素着色器会写入这些目标中的任何一个,如果它返回一个float4,返回一个结构似乎永远不会起作用,并且只会产生渲染目标的清晰颜色。我也尝试过这个返回结构但没有成功:

struct PixelOutputType
{
    float4 position : SV_TARGET
};

感谢您抽出宝贵时间阅读本文。我非常感谢你的帮助。

-T

编辑: 我也尝试过使用ID3D11RenderTargetView *的静态数组,但问题相同。 EDIT2:我还启用了DirectX控制面板输出,看不出任何异常。

1 个答案:

答案 0 :(得分:0)

经过大量的测试和挫折,我终于发现了我的问题; __;

纹理,视图或状态没有问题,但着色器和SV_POSITION存在问题。

我错误地尝试使用我的像素着色器输入&#39; float4位置:SV_TARGET&#39;作为我的输出位置,只将其转换为顶点着色器中的世界坐标。在思考了一段时间之后,我意识到这必须是完全转换的点作为像素着色器的输入,当然,完全转换它可以解决问题。

此:

output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);

而不是:

output.position = mul(input.position, worldMatrix);
//output.position = mul(output.position, viewMatrix);
//output.position = mul(output.position, projectionMatrix);