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

Lares

1x Contest-Sieger

  • »Lares« ist der Autor dieses Themas
  • Private Nachricht senden

1

08.01.2012, 18:26

DirectX 11 Sprites "verschmelzen" nicht

Hallo zusammen,
ich arbeite mich gerade in DirectX11 ein und will mir dazu ne eigene „Engine“ schreiben (keine Sorge keine CryEngine 4). Ich möchte diese mit steigernder Komplexität meiner Projekte erweitern.
Ich hänge aber bereits an einer wahrscheinlich sehr simplen Sache, weiß aber nicht genau woran es liegt. Ich möchte erreichen, dass Sprites übereinander angezeigt werden können. Das heißt das Rechteck des einen Sprites soll nicht das andere „abschneiden“, wie es momentan der Fall ist (siehe Anhang). Das Testsprite, ist hier das Wort „sprite“.
Das ganze soll ja mit Alpha Blending zu lösen sein, ich weiß aber nicht, wo genau der Fehler bei mir liegt. Es liegt entweder
a) an den Blenddeskriptor, der aber gemäß verschiedener Tutorials richtig sein sollte
b) an den HLSL Code l(ich muss gestehen ich habe noch keine Ahnung von den Shadern,deswegen vermute ich da den Fehler)
c) an der Matrizenberechnung oder dem Setzten der Buffer etc.

Soweit meine Eingrenzung, hier die (meiner Meinung nach) relevanten Stellen im Code:

CDrawableObject:
Das ist die Klasse, welche für das Rendern eines Sprites zuständig ist. Sie hat einen eigenen VertexBuffer, ein eigenen ShaderResourceView und einen eigenen SamplerState.
Die Rendermethode sieht folgendermaßen aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
void CDrawableObject::Render(ID3D11DeviceContext* deviceContext)
 {
  unsigned int stride = sizeof( LGE::VertexType );
  unsigned int offset = 0;
  deviceContext->IASetVertexBuffers( 0, 1, &m_VertexBuffer, &stride, &offset );

  deviceContext->PSSetShaderResources( 0, 1, &m_ColorMap);
  deviceContext->PSSetSamplers( 0, 1, &m_ColorMapSampler);

  deviceContext->Draw(m_VertexCount,0);
 }


CGame:
Hat 2 Sprites, eine Kamera und einen 3D Cube (den allerdings noch nicht als eigene Klasse, weswegen CGame::Render noch ein bisschen seltsam aussieht).

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void CGame::Render()
{ 
 if(!m_D3D->GetDeviceContext())
  return;

 m_D3D->BeginScene(); //säubert RenderViewTarget und DepthStencilView
 
 
 unsigned int stride = sizeof( LGE::VertexType );
 unsigned int offset = 0;


 m_Shader->SetShaderParameters(m_D3D->GetDeviceContext());

 m_D3D->GetDeviceContext()->IASetVertexBuffers( 0, 1, &m_VertexBuffer, &stride, &offset );
 m_D3D->GetDeviceContext()->IASetIndexBuffer(m_IndexBuffer, DXGI_FORMAT_R16_UINT, 0 );

 m_D3D->GetDeviceContext()->PSSetShaderResources( 0, 1, &m_ColorMap);
 m_D3D->GetDeviceContext()->PSSetSamplers( 0, 1, &m_ColorMapSampler);
 
 XMMATRIX worldMat = XMMatrixIdentity( );
 worldMat = XMMatrixTranspose( worldMat );
 
 XMMATRIX viewMat = m_Camera.GetViewMatrix( );
 viewMat = XMMatrixTranspose( viewMat );
 

 
 m_D3D->GetDeviceContext()->UpdateSubresource(m_WorldCB, 0, 0, &worldMat, 0, 0 );
 m_D3D->GetDeviceContext()->UpdateSubresource(m_ViewCB, 0, 0, &viewMat, 0, 0 );
 m_D3D->GetDeviceContext()->UpdateSubresource(m_ProjCB, 0, 0, &m_ProjMatrix, 0, 0 );

 m_D3D->GetDeviceContext()->VSSetConstantBuffers( 0, 1, &m_WorldCB );
 m_D3D->GetDeviceContext()->VSSetConstantBuffers( 1, 1, &m_ViewCB );
 m_D3D->GetDeviceContext()->VSSetConstantBuffers( 2, 1, &m_ProjCB);
 m_D3D->GetDeviceContext()->DrawIndexed( 36, 0, 0 );

//    Draw the sprites

 viewMat  = XMMatrixTranspose( viewMat ); //return to original form
 for( int i = 0; i < 2; i++ )
 {
  worldMat = m_Sprite[i].GetWorldMatrix(); 
  worldMat = XMMatrixMultiply( m_Sprite[i].GetWorldMatrix(), viewMat);
  worldMat = XMMatrixTranspose( worldMat );

  m_D3D->GetDeviceContext()->UpdateSubresource(m_WorldCB, 0, 0, &worldMat, 0, 0 );
  m_D3D->GetDeviceContext()->UpdateSubresource(m_ViewCB, 0, 0, &viewMat, 0, 0 );
  m_D3D->GetDeviceContext()->UpdateSubresource(m_ProjCB, 0, 0, &m_ProjMatrix, 0, 0 );

  m_D3D->GetDeviceContext()->VSSetConstantBuffers( 0, 1, &m_WorldCB );
  m_D3D->GetDeviceContext()->VSSetConstantBuffers( 1, 1, &m_ViewCB );
  m_D3D->GetDeviceContext()->VSSetConstantBuffers( 2, 1, &m_ProjCB);
  m_Sprite[i].Render(m_D3D->GetDeviceContext());
 }
 
 m_D3D->EndScene();
}


CGame hat auch einen Alphablendstate. Dieser wird so initialisiert:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
D3D11_BLEND_DESC blendDesc;
ZeroMemory( &blendDesc, sizeof( blendDesc ) );
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
m_D3D->GetDevice()->CreateBlendState( &blendDesc, &m_AlphaBlendState);
m_D3D->GetDeviceContext()->OMSetBlendState( m_AlphaBlendState, blendFactor,0xFFFFFFFF );

Und zum Schluss noch der HLSL Code

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
Texture2D colorMap_ : register( t0 );
SamplerState colorSampler_ : register( s0 );


cbuffer cbChangesEveryFrame : register( b0 )
{
    matrix worldMatrix;
};

cbuffer cbNeverChanges : register( b1 )
{
    matrix viewMatrix;
};

cbuffer cbChangeOnResize : register( b2 )
{
    matrix projMatrix;
};


struct VS_Input
{
    float4 pos  : POSITION;
    float2 tex0 : TEXCOORD0;
};

struct PS_Input
{
    float4 pos  : SV_POSITION;
    float2 tex0 : TEXCOORD0;
};


PS_Input VS_Main( VS_Input vertex )
{
    PS_Input vsOut = ( PS_Input )0;
    vsOut.pos = mul( vertex.pos, worldMatrix );
    vsOut.pos = mul( vsOut.pos, viewMatrix );
    vsOut.pos = mul( vsOut.pos, projMatrix );
    vsOut.tex0 = vertex.tex0;

    return vsOut;
}


float4 PS_Main( PS_Input frag ) : SV_TARGET
{
    return colorMap_.Sample( colorSampler_, frag.tex0 );
}


Vielen Dank schon mal für die Hilfe. Ich weiß ist viel Code,aber da ich nicht sicher bin, in welchen Bereich der Fehler liegt, hab ich lieber etwas mehr Code eingefügt.
»Lares« hat folgendes Bild angehängt:
  • alphablending.png

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

08.01.2012, 18:38

Das liegt am Z-Buffer. Abschalten und/oder manuell in richtiger Reihenfolge von hinten nach vorne rendern.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

08.01.2012, 18:39

Es sollte tatsächlich am BlendState liegen.
Versuche mal SrcBlendAlpha auf den gleichen Wert wie SrcBlend und DestBlendAlpha auf den wie DestBlend zu setzen.
Denn so wie du es momentan hast wird Alphatransparenz gar nicht mit einberechnet.

EDIT: Ohh sry hab vergessen, dass du einen Z-Buffer benutzt.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

08.01.2012, 18:40

Wie man beim Würfel sieht, funktioniert die Transparenz der Sprites, nur ist die Reihenfolge verkehrt und es wird z-Culling gemacht.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Lares

1x Contest-Sieger

  • »Lares« ist der Autor dieses Themas
  • Private Nachricht senden

5

08.01.2012, 18:57

Danke für die schnelle Antwort. Werde das mit den Z-Buffer probieren.^^


Edit: So hat funktioniert danke nochmal
Habe jetzt noch ne designtechnische Frage wegen den An/Ausschalten des Z-Buffers.
Habe diese Methode geschrieben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool CDirect3D::SetDepthStencilState(bool bOn)
 {
  // Create the depth stencil state.
  D3D11_DEPTH_STENCIL_DESC  desc;
  m_DepthStencilState->GetDesc(&desc);
  desc.DepthEnable = bOn;
  HRESULT result = m_D3DDevice->CreateDepthStencilState(&desc, &m_DepthStencilState);
  if(FAILED(result))
  {
   DXTRACE_MSG( "Failed to create the depth stencil state!" );
   return false;
  }
  m_D3DContext->OMSetDepthStencilState(m_DepthStencilState, 1);
  return true;
 }

Es wird somit pro frame 2x "m_D3DDevice->CreateDepthStencilState(&desc, &m_DepthStencilState);" aufgerufen. In einen Tutorial hab ich gesehen, dass derjenige sich extra zwei States gemacht hat, die sich nur in DepthEnable unterscheiden. Meine Frage ist jetzt: Ist das ein deutlicher Performanceverlust, wenn man jedesmal nen neuen State erstellt, oder ist das eher persönliche Präferenz?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Lares« (08.01.2012, 19:36)


TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

6

08.01.2012, 19:41

Das ist nicht nur eine Präferenz, das ist wirklich besser. Denn du verwendest dieselben Objekte wieder und erstellst nicht ständig neue, die sogar zueinander identisch sind. Würde ich auf jeden Fall auch tun ;)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

08.01.2012, 19:46

Genau, es ist gerade einer der ganz großen Vorteile der neuen API dass man separate State-Objekte hat. Mit dieser Vorgehensweise oben machst du den komplett zunichte.
Generell wird beim Rendern idealerweise niemals irgendwas dessen Name mit Create beginnt aufgerufen, das sollte, wenn möglich, schon alles beim Laden passiert sein ;)

Lares

1x Contest-Sieger

  • »Lares« ist der Autor dieses Themas
  • Private Nachricht senden

8

09.01.2012, 09:22

Ok danke, dann werde ich das noch umändern.

Werbeanzeige