一次渲染渲染到完整的3D渲染目标

问题描述 投票:5回答:1

使用DirectX 11,我创建了一个可以绑定为渲染目标的3D体积纹理:

D3D11_TEXTURE3D_DESC texDesc3d;
// ...
texDesc3d.Usage     = D3D11_USAGE_DEFAULT;
texDesc3d.BindFlags = D3D11_BIND_RENDER_TARGET;

// Create volume texture and views
m_dxDevice->CreateTexture3D(&texDesc3d, nullptr, &m_tex3d);
m_dxDevice->CreateRenderTargetView(m_tex3d, nullptr, &m_tex3dRTView);

我现在想要更新整个渲染目标并用像素着色器中生成的程序数据填充它,类似于使用“全屏通道”更新2D渲染目标。生成数据所需的一切都是所讨论像素的UVW坐标。

对于2D,可以构建渲染全屏三角形的简单顶点着色器:

struct VS_OUTPUT
{
    float4 position : SV_Position;
    float2 uv: TexCoord;
};

// input: three empty vertices
VS_OUTPUT main( uint vertexID : SV_VertexID )
{
    VS_OUTPUT result;
    result.uv = float2((vertexID << 1) & 2, vertexID & 2);
    result.position = float4(result.uv * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
    return result;
}

我很难绕过如何采用3D原理。这甚至可以在DirectX 11中使用,还是我必须渲染到体积纹理的各个切片,如here所述?

directx-11 hlsl rendertarget 3d-texture
1个回答
2
投票

以下是使用管道版本执行此操作的示例代码。您基本上批处理N个三角形,并使用Geometry Shader将每个实例路由到卷切片。

struct VS_OUTPUT
{
    float4 position : SV_Position;
    float2 uv: TexCoord;
    uint index: SLICEINDEX;
};

VS_OUTPUT main( uint vertexID : SV_VertexID, uint ii : SV_InstanceID )
{
    VS_OUTPUT result;
    result.uv = float2((vertexID << 1) & 2, vertexID & 2);
    result.position = float4(result.uv * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
    result.index= ii;
    return result;
}

现在,您需要使用3个顶点和N个实例调用DrawInstanced,其中N是您的卷切片计数

然后你像这样给GS分配三角形:

struct psInput
{
    float4 pos : SV_POSITION;
    float2 uv: TEXCOORD0;
uint index : SV_RenderTargetArrayIndex; //This will write your vertex to a specific slice, which you can read in pixel shader too
};

[maxvertexcount(3)] 
void GS( triangle VS_OUTPUT input[3], inout TriangleStream<psInput> gsout )
{       
psInput output;
for (uint i = 0; i < 3; i++)
{
    output.pos = input[i].pos;
    output.uv = input[i].uv;
    output.index= input[0].index; //Use 0 as we need to push a full triangle to the slice
    gsout.Append(output);
}
gsout.RestartStrip();
}

现在您可以访问像素着色器中的切片索引:

float4 PS(psInput input) : SV_Target
{
//Do something with uvs, and use slice input as Z
}

计算着色器版本(不要忘记为你的卷创建一个无人机),这里的numthreads完全是arbirtary

[numthreads(8,8,8)]
void CS(uint3 tid : SV_DispatchThreadID)
{
     //Standard overflow safeguards

     //Generate data using tid coordinates
} 

现在你需要调用宽度为/ 8,高度/ 8,深度/ 8的调度

© www.soinside.com 2019 - 2024. All rights reserved.