Как записать глубину в текстуру и прочитать ее при следующем проходе шейдера в DirectX11?

Я программирую двухпроходный эффект в DirectX 11 (SharpDX). Предполагается записать глубину в текстуру в первом проходе, а затем использовать эту текстуру для извлечения данных из второго прохода в пиксельном шейдере.

Я получаю белый экран, на котором нет ничего, кроме интерфейса, и я не знаю, почему ничего не печатается. В чем может быть проблема? Я бы сказал, что должен получить хоть что-то от Текстуры Глубины. Есть ли более простой способ получить то, к чему я стремлюсь?

Для информации о том, чем я занимаюсь:

Вот как я устанавливаю значения текстуры глубины:

this.depthBuffer = new Texture2D(device, new Texture2DDescription()
        {
            Format = Format.R32_Typeless,
            ArraySize = 1,
            MipLevels = 1,
            Width = (int)host.ActualWidth,
            Height = (int)host.ActualHeight,
            SampleDescription = new SampleDescription(1, 0),
            Usage = ResourceUsage.Default,
            BindFlags = BindFlags.DepthStencil | BindFlags.ShaderResource,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.None,
        });

this.depthBufferShaderResourceView = new ShaderResourceView(this.device, this.depthBuffer, new ShaderResourceViewDescription()
        {
            Format = Format.R32_Float,
            Dimension = ShaderResourceViewDimension.Texture2D,
            Texture2D = new ShaderResourceViewDescription.Texture2DResource()
            {
                MipLevels = 1,
                MostDetailedMip = 0,
            }
        });
var depthStencilDesc = new DepthStencilStateDescription()
        {
            DepthComparison = Comparison.LessEqual,
            DepthWriteMask = global::SharpDX.Direct3D11.DepthWriteMask.All,
            IsDepthEnabled = true,
        };

А вот как я пробую глубину в файле .fx:

int3 posTex = int3(input.p.xy, 0);
float depthPixel = DepthTexture.Load(posTex);
float4 color = float4(depthPixel, depthPixel , depthPixel, 1.0f );
return color;

И вот как я сейчас устанавливаю вид трафарета Depth Buffer как Render Target за 2 прохода. В первом я пытаюсь установить представление глубины в качестве цели. Во втором проходе я пытаюсь установить текстуру глубины в качестве ресурса шейдера для чтения из нее.

this.device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(this.vertexBuffer, LinesVertex.SizeInBytes, 0));

// PASS 0
this.device.ImmediateContext.OutputMerger.SetTargets(depthBufferStencilView);
this.device.ImmediateContext.ClearDepthStencilView(this.depthBufferStencilView,     DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);
this.technique.GetPassByIndex(0).Apply(this.device.ImmediateContext);
this.device.ImmediateContext.DrawIndexed(this.geometry.Indices.Length, 0, 0);

// PASS 1
this.device.ImmediateContext.OutputMerger.ResetTargets(); // unbinding the depthStencilView

this.device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(this.vertexBuffer, LinesVertex.SizeInBytes, 0));
this.depthStencilShaderResourceVariable = effect.GetVariableByName("DepthTexture").AsShaderResource();
this.depthStencilShaderResourceVariable.SetResource(this.depthBufferShaderResourceView);
this.technique.GetPassByIndex(1).Apply(this.device.ImmediateContext);
this.device.ImmediateContext.DrawIndexed(this.geometry.Indices.Length, 0, 0);

Наконец, вот как я установил два прохода в файле .fx:

technique11 RenderMyTechnique
{
pass P0
{   

SetDepthStencilState( DSSDepthLessEqual, 0 );
SetVertexShader     ( CompileShader( vs_4_0, VShader() ) );
    SetHullShader       ( NULL );
    SetDomainShader     ( NULL );        
    SetGeometryShader   ( NULL  );
SetPixelShader      ( NULL );
}

pass P1
{
SetDepthStencilState( DSSDepthLessEqual, 0 );
SetVertexShader     ( CompileShader( vs_4_0, VShader() ) );
    SetHullShader       ( NULL );
    SetDomainShader     ( NULL );        
    SetGeometryShader   ( CompileShader( gs_4_0, GShader() ) );
SetPixelShader      ( CompileShader( ps_4_0, PShader() ) );
}
}

person c4sh    schedule 19.11.2013    source источник


Ответы (1)


Когда вы звоните:

this.device.ImmediateContext.OutputMerger.ResetTargets();

После этого вы выполняете отрисовку напрямую, вы не привязываете к ней никакой цели рендеринга, поэтому вам нужно вызвать:

this.device.ImmediateContext.OutputMerger.SetTargets(renderView);

renderview — это любое представление rendertarget (может быть вашей цепочкой обмена). На данный момент вы делаете ничью, но «ни к чему».

Вторая потенциальная проблема: вы перерисовываете одну и ту же модель, но без трафарета глубины, поэтому результаты могут отличаться (особенно потому, что в одной версии вы используете шейдер геометрии, а в другой нет). Таким образом, ваши данные о глубине из предыдущего прохода могут быть вообще неверными.

person mrvux    schedule 19.11.2013