Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

1

28.02.2010, 16:28

[D3D11] Probleme mit multisampled Depth Buffer

Hi Leute!
Wie im Titel schon erwähnt, habe ich Probleme mit dem Depth-Buffer.
Ein multisampled RenderTarget kann ich problemlos erstellen, aber der Depth-Buffer macht (bei eingeschaltetem) Multisampling Probleme.

Aber seht selbst, denn Code sagt mehr als tausend Worte.
Hier wird das RenderTarget und der DepthBuffer erstellt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//////////////////////////////////////////////////////////////////

//RenderTargets erstellen

//Back-Buffer

D3D11_TEXTURE2D_DESC BufferTextureDesc;
BufferTextureDesc.Width             = VideoSettings.dwBBSizeX;
BufferTextureDesc.Height            = VideoSettings.dwBBSizeY;
BufferTextureDesc.MipLevels         = 1;
BufferTextureDesc.ArraySize         = 1;
BufferTextureDesc.Format            = VideoSettings.bHDRR ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_R8G8B8A8_UNORM;
BufferTextureDesc.SampleDesc.Count  = VideoSettings.dwMultiSamplingType ? VideoSettings.dwMultiSamplingType : 1;
BufferTextureDesc.SampleDesc.Quality= Video::FindMaxMultisamplingQuality(pVideo->GetFactory(), VideoSettings.dwAdapter, VideoSettings.bHDRR, VideoSettings.dwMultiSamplingType);
BufferTextureDesc.Usage             = D3D11_USAGE_DEFAULT;
BufferTextureDesc.BindFlags         = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE;
BufferTextureDesc.CPUAccessFlags    = 0;
BufferTextureDesc.MiscFlags         = 0;

TRY_DX(pDevice->CreateTexture2D(&BufferTextureDesc, NULL, &pBackBufferTexture));
TRY_DX(pDevice->CreateRenderTargetView(pBackBufferTexture, NULL, &pBackBufferRTV));
TRY_DX(pDevice->CreateShaderResourceView(pBackBufferTexture, NULL, &pBackBufferSRV));

//Depth-Stencil-Buffer

BufferTextureDesc.Format            = DXGI_FORMAT_R32_TYPELESS;
BufferTextureDesc.BindFlags         = D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE;
TRY_DX(pDevice->CreateTexture2D(&BufferTextureDesc, NULL, &pDepthBufferTexture)); //<-- Hier kackt er ab! Fehler Code: E_INVALIDARG


D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc;
DSVDesc.Format                      = DXGI_FORMAT_D32_FLOAT;
DSVDesc.ViewDimension               = VideoSettings.dwMultiSamplingType ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
DSVDesc.Flags                       = 0;
DSVDesc.Texture2D.MipSlice          = 0;
TRY_DX(pDevice->CreateDepthStencilView(pDepthBufferTexture, &DSVDesc, &pDepthBufferDSV));

D3D11_SHADER_RESOURCE_VIEW_DESC DSSRVDesc;
DSSRVDesc.Format                    = DXGI_FORMAT_R32_FLOAT;
DSSRVDesc.ViewDimension             = VideoSettings.dwMultiSamplingType ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
DSSRVDesc.Texture2D.MipLevels       = 1;
DSSRVDesc.Texture2D.MostDetailedMip = 0;
TRY_DX(pDevice->CreateShaderResourceView(pDepthBufferTexture, &DSSRVDesc, &pDepthBufferSRV));

VideoSettings.dwMultiSamplingType gibt hier den Multisampling Count an, wobei für 0 Sample Count 1 ist.

Ich bin am Verzweifeln... :(
Wer findet den Fehler?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

28.02.2010, 17:05

Was sagt die Debugruntime dazu? Unterstützt deine Grafikkarte das Format DXGI_FORMAT_R32_TYPELESS für einen DepthBuffer in Kombination mit den Sample Einstellungen überhaupt!?

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

3

28.02.2010, 17:09

Ich hab gerade noch was herausgefunden:
Wenn ich die DepthTexture ohne ShaderResource-Bindflag erstelle und später gar kein ShaderResourceView erstelle, geht es.
Allerdings heißt das jetzt, dass ich den DepthBuffer nicht mehr im Shader lesen kann.

Ich müsste also noch eine Depth-Textur(SRV) als Shader-Resource erzeugen, und in diese dann die benutze DepthTexture(DSV) resolven.
Das ist aber auch nicht gerade das gelbe vom Ei.

Kennt sich da jemand aus?

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

4

28.02.2010, 17:16

Zitat von »"dot"«

Was sagt die Debugruntime dazu? Unterstützt deine Grafikkarte das Format DXGI_FORMAT_R32_TYPELESS für einen DepthBuffer in Kombination mit den Sample Einstellungen überhaupt!?

Ja, das tut sie. Ersteres muss sie sogar, sonst gäbe es kein D3D10-Siegel und die Sample-Einstellungen habe ich überprüft -> klappt.

Wie gesagt, ohne SRV klappt es, aber ich brauch diesen verdammten SRV.

Die DebugRuntime sagt dazu garnichts. Nur der Return-Wert ist eben E_INVALIDARG.

EDIT: Mit erhöhter Debug-Stufe kam folgendes Ergebnis:

Quellcode

1
D3D11: ERROR: ID3D11Device::CreateTexture2D: If the device interface is D3D10.0 or the driver/hardware are D3D10.0 (regardless of API version), a Texture2D with sample count > 1 cannot have both D3D11_BIND_DEPTH_STENCIL and D3D11_BIND_SHADER_RESOURCE.  This call may appear to incorrectly return success on older/current D3D runtimes due to missing validation, despite this debug layer message.  [ STATE_CREATION ERROR #99: CREATETEXTURE2D_INVALIDBINDFLAGS ]


Verdammt!

Also doch Resolven.
Gibt es keine andere Möglichkeit? Vieleicht ein zusätzliches R32_FLOAT RenterTarget unabhängig vom Z-Buffer, wo per PixelShader die Depth-Werte gespeichert werden?

BlackSnake

Community-Fossil

Beiträge: 1 549

Beruf: Student

  • Private Nachricht senden

5

28.02.2010, 17:41

erstell ein zweites render target (r32) und setze dies. im shader dann die tiefenwerte in dieses target schreiben und du hast das gleiche ergebnis. geht aber nur, wenn du den tiefenbuffer nicht schon hauptgang benötigst, sondern nur post processing gang...
evtl greifst du dann im post process shader die einzelnen samples ab.

schreiben in zwei gesetzte targets machste mit dem geometry shader -> SV_Target[n]

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

6

28.02.2010, 18:56

Zitat von »"BlackSnake"«


schreiben in zwei gesetzte targets machste mit dem geometry shader -> SV_Target[n]

Hat das Vorteile gegenüber dem PixelShader?

Dann mach ich das so mit dem 2. RT.

EDIT: Wie komme ich im PixelShader / Geometrie Shader an den Z-Wert?
Halbwegs anschaulich sieht

Quellcode

1
Out.Depth.rgb= 1.0F - pow(In.vPosition.z, 16);

aus, aber das ist es doch nicht, oder?

BlackSnake

Community-Fossil

Beiträge: 1 549

Beruf: Student

  • Private Nachricht senden

7

28.02.2010, 19:04

du kannst bei dem pixelshader gar nicht angeben, in welches target du schreiben willst, dies geht nur bei dem geometry shader.

du schreibst einfach die z position da rein. du hast dann auch nur ".r", da du ja ne 32bit float texture verwendest

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

8

28.02.2010, 20:41

Die Doku sagt aber:

Zitat

SV_Target[n], where 0 <= n <= 7

The output value that will be stored in a render target. The index indicates which of the 8 possibly bound render targets to write to. The value is available as output from the pixel shader. (write only)


Und das hier schluckt zumindest der Shader Compiler:

C-/C++-Quelltext

1
2
3
4
5
6
struct PSOutput
{
    float4 Color            : SV_Target0;
    float Depth             : SV_Target1;
    float4 ViewNormal       : SV_Target2;
};

Ob da tatsächlich was rauskommt, müsste ich erst probieren.


Könntest du vieleicht zeigen, wie das mit einem Geometry Shader geht?
Ich kann mir beim besten Willen nicht vorstellen, wie das gehen soll.
Ich steh in der Beziehung gerade ziemlich auf dem Schlauch. :)

BlackSnake

Community-Fossil

Beiträge: 1 549

Beruf: Student

  • Private Nachricht senden

9

28.02.2010, 21:09

ah sry^^. du musst das hier nehme: SV_RenderTargetArrayIndex
voll vertan :(

es gibt im sdk ein ganz nettes sample. die doku dazu sieh so aus:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
Sample Overview
Environment mapping is a popular and well-supported technique in 3D graphics. Traditionally, dynamic cubic environment maps are created by obtaining a surface for each face of a cube texture and setting that surface as the render target to render the scene once for each face of the cube. The cube texture can then be used to render environment-mapped objects. This method, while it works, increases the number of rendering passes from one to seven, greatly reducing the application frame rate. In Direct3D 10, applications can use geometry shaders and render target arrays to alleviate this problem.

How the Sample Works
A geometry shader in Direct3D 10 is a piece of code that runs for each primitive to be rendered. In each invocation, the geometry shader can output zero or more primitives to be rasterized and processed in the pixel shader. For each output primitive, the geometry shader can also control to which element slice of the render target array the primitive gets emitted.

The render target array in Direct3D 10 is a feature that enables an application to render onto multiple render targets simultaneously at the primitive level. The application uses a geometry shader to output a primitive and select which render target in the array should receive the primitive. This sample uses a render target array of 6 elements for the 6 faces of the cube texture. The following code fragment creates the render target view used for rendering to the cube texture.

// Create the 6-face render target view
D3D10_RENDER_TARGET_VIEW_DESC DescRT;
DescRT.Format = dstex.Format;
DescRT.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DARRAY;
DescRT.Texture2DArray.FirstArraySlice = 0;
DescRT.Texture2DArray.ArraySize = 6;
DescRT.Texture2DArray.MipSlice = 0;
pd3dDevice->CreateRenderTargetView( g_pEnvMap, &DescRT, &g_pEnvMapRTV );

By setting DescRT.TextureCube.FirstArraySlice to 0 and DescRT.TextureCube.ArraySize to 6, this render target view represents an array of 6 render targets, one for each face of the cube texture. When the sample renders onto the cube map, it sets this render target view as the active view by calling ID3D10Device::OMSetRenderTargets() so that all 6 faces of the texture can be rendered at the same time.

// Set the env map render target and depth stencil buffer
ID3D10RenderTargetView* aRTViews[ 1 ] = { g_apEnvMapOneRTV[view] };
pd3dDevice->OMSetRenderTargets( sizeof(aRTViews) / sizeof(aRTViews[0]), 
    aRTViews, g_pEnvMapOneDSV );

Rendering the CubeMap
At the top level, rendering begins in Render(), which calls RenderSceneIntoCubeMap() and RenderScene(), in that order. RenderScene() takes a view matrix a projection matrix, then renders the scene onto the current render target. RenderSceneIntoCubeMap() handles rendering of the scene onto a cube texture. This texture is then used in RenderScene() to render the environment-mapped object.

In RenderSceneIntoCubeMap(), the first necessary task is to compute the 6 view matrices for rendering to the 6 faces of the cube texture. The matrices have the eye point at the camera position and the viewing directions along the -X, +X, -Y, +Y, -Z, and +Z directions. A boolean flag, m_bUseRenderTargetArray, indicates the technique to use for rendering the cube map. If false, a for loop iterates through the faces of the cube map and renders the scene by calling RenderScene() once for each cube map face. No geometry shader is used for rendering. This technique is essentially the legacy method used in Direct3D 9 and prior. If m_bUseRenderTargetArray is true, the cube map is rendered with the RenderCubeMap effect technique. This technique uses a geometry shader to output each primitive to all 6 render targets. Therefore, only one call to RenderScene() is required to draw all 6 faces of the cube map.

The vertex shader that is used for rendering onto the cube texture is VS_CubeMap, as shown below. This shader does minimal work of transforming vertex positions from object space to world space. The world space position will be needed in the geometry shader.

struct VS_OUTPUT_CUBEMAP
{
    float4 Pos : SV_POSITION;    // World position
    float2 Tex : TEXCOORD0;      // Texture coord
};
VS_OUTPUT_CUBEMAP VS_CubeMap( float4 Pos : POSITION, float3 Normal : NORMAL, float2 Tex : TEXCOORD )
{
    VS_OUTPUT_CUBEMAP o = (VS_OUTPUT_CUBEMAP)0.0f;

    // Compute world position
    o.Pos = mul( Pos, mWorld );

    // Propagate tex coord
    o.Tex = Tex;

    return o;
}

One of the two geometry shaders in this sample, GS_CubeMap, is shown below. This shader is run once per primitive that VS_CubeMap has processed. The vertex format that the geometry shader outputs is GS_OUTPUT_CUBEMAP. The RTIndex field of this struct has a special semantic: SV_RenderTargetArrayIndex. This semantic enables the field RTIndex to control the render target to which the primitive is emitted. Note that only the leading vertex of a primitive can specify a render target array index. For all other vertices of the same primitive, RTIndex is ignored and the value from the leading vertex is used. As an example, if the geometry shader constructs and emits 3 vertices with RTIndex equal to 2, then this primitive goes to element 2 in the render target array.

At the top level, the shader consists of a for loop that loops 6 times, once for each cube face. Inside the loop, another loop runs 3 times per cube map to construct and emit three vertices for the triangle primitive. The RTIndex field is set to f, the outer loop control variable. This ensures that in each iteration of the outer loop, the primitive is emitted to a distinct render target in the array. Another task that must be done before emitting a vertex is to compute the Pos field of the output vertex struct. The semantic of Pos is SV_POSITION, which represents the projected coordinates of the vertex that the rasterizer needs to properly rasterize the triangle. Because the vertex shader outputs position in world space, the geometry shader needs to transform that by the view and projection matrices. In the loop, the view matrix used to transform the vertices is g_mViewCM[f]. This array of matrix is filled by the sample and contains the view matrices for rendering the 6 cube map faces from the environment-mapped object's perspective. Thus, each iteration uses a different view transformation matrix and emits vertices to a different render target. This renders one triangle onto 6 render target textures in a single pass, without calling DrawIndexed() multiple times.

struct GS_OUTPUT_CUBEMAP
{
    float4 Pos : SV_POSITION;     // Projection coord
    float2 Tex : TEXCOORD0;       // Texture coord
    uint RTIndex : SV_RenderTargetArrayIndex;
};

[maxvertexcount(18)]
void GS_CubeMap( triangle VS_OUTPUT_CUBEMAP In[3], inout TriangleStream<GS_OUTPUT_CUBEMAP> CubeMapStream )
{
    for( int f = 0; f < 6; ++f )
    {
        // Compute screen coordinates
        GS_OUTPUT_CUBEMAP Out;
        Out.RTIndex = f;
        for( int v = 0; v < 3; v++ )
        {
            Out.Pos = mul( In[v].Pos, g_mViewCM[f] );
            Out.Pos = mul( Out.Pos, mProj );
            Out.Tex = In[v].Tex;
            CubeMapStream.Append( Out );
        }
        CubeMapStream.RestartStrip();
    }
}

The pixel shader, PS_CubeMap, is rather straight-forward. It fetches the diffuse texture and applies it to the mesh. Because the lighting is baked into this texture, no lighting is performed in the pixel shader.

vorne und hinten fehlt bissen was, ist nur auf das nötigste bschränkt. mit dem sample versteht man das prima :)
name des samples: CubeMapGS

bei fragen stehe ich gerne zu verfügung und wenn es mit dem sample nicht so klappt, wie du es dir vorstellst, erkläre ich noch mal ausführlich und in langsamen schritten :) aber teste erstmal mit dem sample, da es ansich schon gut ist
schönen abend noch :)

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

10

02.03.2010, 19:23

Danke für das Sample, aber das nützt mir recht wenig, da es auf TextureArrays aufbaut.
Ich habe insgesamt 3 RenderTargets in verdschiedenen Formaten:
1. Das ganz normale gerenderte Bild in HDR (R16G16B16A16_FLOAT)
2. "Depth" - Tiefeninfos (R32_FLOAT)
3. "Normals" - Normalmap des gerenderten Bildes (R8G8B8A8_UNORM)

Ich brauch also nicht SV_RenderTargetArrayIndex sondern SV_Target[n]. Und kann ich das auch im GS oder vleieicht sogar im VS setzen?

Werbeanzeige