HLSL 渲染到纹理的问题
Problems with HLSL render to texture
问题:
如何通过 return 具有语义映射的结构通过 HLSL 渲染到目标?
你好。我是 DirectX11 的新手,正在尝试设置渲染到纹理,以便我可以实现延迟着色。我花了一天多的时间在网上搜索我的问题的解决方案,但到目前为止没有运气。
目前,我可以通过 HLSL 将我的场景渲染为单个纹理,然后将该纹理毫无问题地渲染为全屏四边形。但是,如果我绑定多个渲染目标,我所看到的只是我的目标的清晰颜色,像素着色器似乎永远不会到达任何绑定纹理。我在运行时设置了 D3D11_CREATE_DEVICE_DEBUG 而没有 warnings/errors,并且我尝试使用 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);
}
}
我的像素着色器将写入这些目标中的任何一个,如果它 return 是 float4,returning 结构似乎永远不会工作,并且只会为渲染目标生成清晰的颜色。我也试过这个作为 return 结构但没有成功:
struct PixelOutputType
{
float4 position : SV_TARGET
};
感谢您花时间阅读本文。非常感谢您的帮助。
-T
编辑:
我也尝试过使用 ID3D11RenderTargetView* 的静态数组,但遇到了同样的问题。
EDIT2:我还启用了 DirectX 控制面板输出,没有发现任何异常。
经过大量的测试和挫折,我终于发现了我的问题;__;
我的纹理、视图或状态没有问题,但着色器和 SV_POSITION 有问题。
我错误地尝试使用我的像素着色器输入 'float4 position : SV_TARGET' 作为我的输出位置,并且只在顶点着色器中将其转换为世界坐标。考虑了一段时间后,我意识到这必须是作为像素着色器输入的完全转换点,果然,完全转换它解决了这个问题。
这个:
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);
问题: 如何通过 return 具有语义映射的结构通过 HLSL 渲染到目标?
你好。我是 DirectX11 的新手,正在尝试设置渲染到纹理,以便我可以实现延迟着色。我花了一天多的时间在网上搜索我的问题的解决方案,但到目前为止没有运气。
目前,我可以通过 HLSL 将我的场景渲染为单个纹理,然后将该纹理毫无问题地渲染为全屏四边形。但是,如果我绑定多个渲染目标,我所看到的只是我的目标的清晰颜色,像素着色器似乎永远不会到达任何绑定纹理。我在运行时设置了 D3D11_CREATE_DEVICE_DEBUG 而没有 warnings/errors,并且我尝试使用 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);
}
}
我的像素着色器将写入这些目标中的任何一个,如果它 return 是 float4,returning 结构似乎永远不会工作,并且只会为渲染目标生成清晰的颜色。我也试过这个作为 return 结构但没有成功:
struct PixelOutputType
{
float4 position : SV_TARGET
};
感谢您花时间阅读本文。非常感谢您的帮助。
-T
编辑: 我也尝试过使用 ID3D11RenderTargetView* 的静态数组,但遇到了同样的问题。 EDIT2:我还启用了 DirectX 控制面板输出,没有发现任何异常。
经过大量的测试和挫折,我终于发现了我的问题;__;
我的纹理、视图或状态没有问题,但着色器和 SV_POSITION 有问题。
我错误地尝试使用我的像素着色器输入 'float4 position : SV_TARGET' 作为我的输出位置,并且只在顶点着色器中将其转换为世界坐标。考虑了一段时间后,我意识到这必须是作为像素着色器输入的完全转换点,果然,完全转换它解决了这个问题。
这个:
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);