Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problemas De Transparencias Con El Z-buffer En D3d

Iniciado por [EX3], 27 de Marzo de 2005, 06:18:20 AM

« anterior - próximo »

[EX3]

 Wenas, despues de activar el Z-Buffer en D3D estuve haciendo pruebas y ya consegui suplantar la interfaz D3DXSprite por un sistema de quads aunque solo me falta el detalle de como definir una porcion de textura que dibujar, pero eso ya es otro asunto aparte.

Estuve haciendo pruebas con el Z-Buffer y he descubierto algo que me ha fastidiado el tema por completo y es que fallan las transparencias segun la profundidad. Como no se explicarlo de forma que se entienda bien he subido el ejemplo compilado y con su codigo fuente incluido para que veais por vuestra cuenta a que me refiero y de paso me digais si esto es normal o no.

Prueba_Z-Buffer.zip - 36.7kb

El codigo del programa es el siguiente:
Option Explicit

Dim Dx As DirectX8
Dim D3D As Direct3D8
Dim D3DDevice As Direct3DDevice8
Dim bRunning As Boolean

Const FVF = D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE Or D3DFVF_SPECULAR

Private Type TLVERTEX
   X As Single
   Y As Single
   Z As Single
   rhw As Single
   Color As Long
   specular As Long
   tu As Single
   tv As Single
End Type

Dim D3DX As D3DX8
Dim Texture As Direct3DTexture8
Dim TransTexture As Direct3DTexture8

Dim mX As Single, mY As Single 'Posicion del raton.
Dim mA As Single 'Contador para el angulo del sprite.

Private Declare Function GetTickCount Lib "kernel32" () As Long
Dim LastTimeCheckFPS As Long
Dim FramesDrawn As Long
Dim FrameRate As Long

Dim Mode As Boolean

Public Function Initialise() As Boolean
On Error GoTo ErrHandler:

Dim DispMode As D3DDISPLAYMODE
Dim D3DWindow As D3DPRESENT_PARAMETERS

Set Dx = New DirectX8
Set D3D = Dx.Direct3DCreate()
Set D3DX = New D3DX8

D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, DispMode
   
D3DWindow.Windowed = 1
D3DWindow.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC
D3DWindow.BackBufferFormat = DispMode.Format
D3DWindow.BackBufferHeight = 480 '//form.Height = 7590
D3DWindow.BackBufferWidth = 640 '//form.Width = 9675
D3DWindow.hDeviceWindow = frmMain.hWnd
   
D3DWindow.EnableAutoDepthStencil = 1
D3DWindow.AutoDepthStencilFormat = D3DFMT_D16

Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, frmMain.hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DWindow)

D3DDevice.SetVertexShader FVF

D3DDevice.SetRenderState D3DRS_LIGHTING, False

D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
D3DDevice.SetRenderState D3DRS_ALPHABLENDENABLE, True

D3DDevice.SetTextureStageState 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR
D3DDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR

D3DDevice.SetRenderState D3DRS_ZENABLE, 1
D3DDevice.SetRenderState D3DRS_ZWRITEENABLE, 0

Set Texture = D3DX.CreateTextureFromFileEx(D3DDevice, App.Path & "\logo.bmp", 50, 50, _
                                                                           D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, _
                                                                           D3DPOOL_MANAGED, D3DX_FILTER_POINT, _
                                                                           D3DX_FILTER_POINT, &HFF00FF00, _
                                                                           ByVal 0, ByVal 0)

Set TransTexture = D3DX.CreateTextureFromFileEx(D3DDevice, App.Path & "\soldier.png", 131, 185, _
                                                                           D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, _
                                                                           D3DPOOL_MANAGED, D3DX_FILTER_POINT, _
                                                                           D3DX_FILTER_POINT, &HFF00FF00, _
                                                                           ByVal 0, ByVal 0)

Initialise = True
Exit Function

ErrHandler:
Initialise = False
End Function

Public Sub Render()
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &HFF0000FF, 1#, 0

D3DDevice.BeginScene
   
   mA = mA + 0.1
   If mA > 359.9 Then mA = 0
   
   If Mode Then
       Me.Tag = "ZBuffer = ON"
       D3DDevice.SetRenderState D3DRS_ZWRITEENABLE, 1
   
       'Dibujamos los quads definiendo su orden por su coordenada Z:
       Call BlitFX(Texture, 200, 20, 0, 200, 200, 0, 0, &HFFFFFFFF, 0, False)
       Call BlitFX(Texture, 0, 0, 0, 200, 200, 0, 0, &HFFFF7700, 2, False)
       Call BlitFX(TransTexture, CLng(mX), CLng(mY), 0, 185, 131, mA, 0, &HFFFFFFFF, 0, True)
       Call BlitFX(TransTexture, CLng(mX) + 50, CLng(mY) + 50, 0, 185, 131, mA, 0, &HFFFFFFFF, 0, True)
       Call BlitFX(TransTexture, CLng(mX) + 100, CLng(mY) + 100, 0, 185, 131, mA, 0, &HFFFFFFFF, 0, True)
   
   Else
       Me.Tag = "ZBuffer = OFF"
       D3DDevice.SetRenderState D3DRS_ZWRITEENABLE, 0
       
       'Dibujamos los quads por orden de profundidad:
       Call BlitFX(TransTexture, CLng(mX) + 100, CLng(mY) + 100, 0, 185, 131, mA, 0, &HFFFFFFFF, 0, True)
       Call BlitFX(Texture, 200, 20, 0, 200, 200, 0, 0, &HFFFFFFFF, 0, False)
       Call BlitFX(TransTexture, CLng(mX) + 50, CLng(mY) + 50, 0, 185, 131, mA, 0, &HFFFFFFFF, 0, True)
       Call BlitFX(Texture, 0, 0, 0, 200, 200, 0, 0, &HFFFF7700, 2, False)
       Call BlitFX(TransTexture, CLng(mX), CLng(mY), 0, 185, 131, mA, 0, &HFFFFFFFF, 0, True)
       
   End If
   
D3DDevice.EndScene

D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0

If GetTickCount - LastTimeCheckFPS >= 1000 Then
   LastTimeCheckFPS = GetTickCount
   FrameRate = FramesDrawn
   FramesDrawn = 0
   Me.Caption = "DirectX-Graphics: {" & FrameRate & "fps}" & " {Pulsar 1 > Z-Buffer = ON / 2 > Z-Buffer = OFF: " & Me.Tag & "}"
End If
FramesDrawn = FramesDrawn + 1

End Sub

Private Sub Form_Click()
bRunning = False
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKey1 Then Mode = True Else If KeyCode = vbKey2 Then Mode = False
End Sub

Private Sub Form_Load()

Me.Show

bRunning = Initialise()

Do While bRunning
   Render
   DoEvents
   
Loop

On Error Resume Next

Set D3DDevice = Nothing
Set D3D = Nothing
Set Dx = Nothing

Unload Me
End
End Sub

Private Function CreateTLVertex(X As Single, Y As Single, Z As Single, rhw As Single, Color As Long, specular As Long, tu As Single, tv As Single) As D3DTLVERTEX
CreateTLVertex.sx = X
CreateTLVertex.sy = Y
CreateTLVertex.sz = Z
CreateTLVertex.rhw = rhw
CreateTLVertex.Color = Color
CreateTLVertex.specular = specular
CreateTLVertex.tu = tu
CreateTLVertex.tv = tv
End Function

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
mX = X
mY = Y
End Sub

Private Sub BlitFX(Texture As Direct3DTexture8, X As Long, Y As Long, Optional Z As Single = 0, Optional Height As Long = 64, Optional Width As Long = 64, Optional Angle As Single, Optional AlphaBlendMode As Long, Optional Color As Long = -1, Optional Mirror As Long, Optional Center As Boolean)
On Error GoTo ErrOut

Const PI As Single = 3.14159265358979

Dim Quad(3) As D3DTLVERTEX
Dim vX As Long, vY As Long, tX As Long, tY As Long, tu(3) As Single, tv(3) As Single

'Generamos el poligono:
   If Center Then
       X = X - (Width / 2)
       Y = Y - (Height / 2)
   End If
     
   Select Case Mirror
       Case 0 'Normal
           tu(0) = 0: tv(0) = 1
           tu(1) = 0: tv(1) = 0
           tu(2) = 1: tv(2) = 1
           tu(3) = 1: tv(3) = 0
       
       Case 1 'Horizontal
           tu(0) = 0: tv(0) = 0
           tu(1) = 0: tv(1) = 1
           tu(2) = 1: tv(2) = 0
           tu(3) = 1: tv(3) = 1
       
       Case 2 'Vertical
           tu(0) = 1: tv(0) = 1
           tu(1) = 1: tv(1) = 0
           tu(2) = 0: tv(2) = 1
           tu(3) = 0: tv(3) = 0
       
       Case 3 'Horizontal/Vertical
           tu(0) = 1: tv(0) = 0
           tu(1) = 1: tv(1) = 1
           tu(2) = 0: tv(2) = 0
           tu(3) = 0: tv(3) = 1
           
   End Select
   
   tX = -Width / 2
   tY = -Height / 2
   vX = tX * Cos(-Angle * PI / 180) + tY * -Sin(-Angle * PI / 180)
   vY = tX * Sin(-Angle * PI / 180) + tY * Cos(-Angle * PI / 180)
   Quad(0) = CreateTLVertex(vX + Width / 2 + X, -vY + Height / 2 + Y, Z, 1, Color, 0, tu(0), tv(0))
   
   tX = -Width / 2
   tY = Height / 2
   vX = tX * Cos(-Angle * PI / 180) + tY * -Sin(-Angle * PI / 180)
   vY = tX * Sin(-Angle * PI / 180) + tY * Cos(-Angle * PI / 180)
   
   Quad(1) = CreateTLVertex(vX + Width / 2 + X, -vY + Height / 2 + Y, Z, 1, Color, 0, tu(1), tv(1))
   
   tX = Width / 2
   tY = -Height / 2
   vX = tX * Cos(-Angle * PI / 180) + tY * -Sin(-Angle * PI / 180)
   vY = tX * Sin(-Angle * PI / 180) + tY * Cos(-Angle * PI / 180)
   Quad(2) = CreateTLVertex(vX + Width / 2 + X, -vY + Height / 2 + Y, Z, 1, Color, 0, tu(2), tv(2))
   
   tX = Width / 2
   tY = Height / 2
   vX = tX * Cos(-Angle * PI / 180) + tY * -Sin(-Angle * PI / 180)
   vY = tX * Sin(-Angle * PI / 180) + tY * Cos(-Angle * PI / 180)
   Quad(3) = CreateTLVertex(vX + Width / 2 + X, -vY + Height / 2 + Y, Z, 1, Color, 0, tu(3), tv(3))

'Pintamos el poligono con la textura:
 
   Select Case AlphaBlendMode
       Case 1 'Efecto Glow:
           D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ONE
           D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE
       
       Case 2 'Efecto Inverso:
           D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR
           D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR

   End Select

   D3DDevice.SetTexture 0, Texture
   
   D3DDevice.SetTextureStageState 0, D3DTSS_MIPFILTER, 3
   D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, Quad(0), Len(Quad(0))
   
Exit Sub

ErrOut:
End Sub

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

_Grey

 Pues no puedo bajar el .zip, de todas formas creo que se lo que pasa por lo que dices, es algo muy tipico y que cuando se toca por primera vez puede llamar la atencion.

Has de dejar los poligonos trasparentes para renderizar al final, y dependiendo de el tipo de trasparencia puede ser necesario que los ordenes de tal forma, que primero se pinten los mas lejanos y termines por el mas proximo.

Saludos.

Thenend

 A _Grey se le ha olvidado decir que cuando pintes los sprites transparentes al final de todo, si no los tienes ordenados por distancia, debes desactivar la escritura del Z-Buffer.

Si miras a través de una ventana que es un polígono con alpha y la pintas lo primero, escribirá el z buffer y todo lo que pintes al otro lado será descartado el hacer el Z test, por eso hay que desactivarlo.

[EX3]

 He subido el zip al server de mi web, desde ahi si os deberia dejar bajarlo sin problemas:

Prueba_Z-Buffer.zip - 36.7 kb

Aun asi he sacado dos capturas para que veais exactamente a lo que me refiero y que parece ser lo que me comentais:


En esta el zbuffer esta desactivado y dibujo los quads segun el orden de dibujo.


En esta el zbuffer esta activado y dibujo los quads sin orden de dibujo. Aplico el orden de dibujo mediante la coordenada Z.

Mi unica intencion de usar el Z-Buffer era poder olvidarme de tener que dibujar los graficos por orden, pudiendo asi pintar por partes y asignado su profundidad mediante la coordenada Z y hasta que probe lo de la transparencia todo iba por buen camino.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

_Grey

 Ahora si pude ver el programa, y tiene toda la pinta de ser lo que comentamos Thenend y yo.

Tambien se puede aplicar una especie de colorKey por alpha, para ver mas sobre esto mira el parametro D3DRS_ALPHATESTENABLE  de SetRenderState. De todas formas podria siguir dando problemas en los bordes visibles del sprite, me temo que tendras que ordenar.

Saludos.

BeRSeRKeR

 Como bien dicen, si quieres utilizar alpha blending tendrás que renderizar de atrás hacia adelante. El problema que estás teniendo es precisamente por el orden incorrecto de render.

Por ejemplo, si cogemos el soldado que está delante de todos, ves que se mezcla bien con el sprite de DX. Eso es porque dicho sprite se renderizó antes que el soldado por lo que la operación de mezcla lo tuvo en cuenta. Pero ahora vemos que no se mezcla bien con el segundo soldado. Eso es porque dicho sprite se renderizó después que el primer soldado por lo que cuando Direct3D fue a calcular la mezcla al renderizar el primer soldado, los pixels que entraban en juego eran el del sprite y el del color actual del frame buffer que en este caso es el azul y no el del segundo soldado (ya que éste se renderizó después).

La otra opcion es, como ha dicho _Grey, utilizar alpha testing. En ese caso no necesitarías ordenar pero los bordes del sprite no te saldrán tan suavizados como con el alpha blending. Aunque es posible que puedas utilizar conjuntamente alpha testing y alpha blending y solucionar ambos problemas, pero de esto no estoy seguro.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

[EX3]

 Si tengo que ordenar me deja mi idea por los suelos, para eso prefiero quitar el z-buffer y hacerme unos arrays donde almaceno los parametros de los quads y textura asociada y me hago una lista de ordenacion, aunque no se como saldra el experimento.

[edit] Acabo de probar lo del alphatesting y cierto, ahora si funciona correctamente excepto por el borde de las texturas, que se difumina. Bueno, ya probe hacer lo de la lista de ordenacion y ya tengo una salida por si no logro solucionar del todo el tema del z-buffer :)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Lord Trancos 2

 Usar el z-buffer acelerará las cosas; asi que si puedes, usalo.

Respecto a usar color-keying, ten en cuenta que no te valdra cuando quieras dibujar un sprite parcialmente transparente.
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

[EX3]

 No se si es normal lo que me paso anoche a ultima hora, cuando hice la prueba del alphatest para lo del z-bufffer me dio por cambiar unas opciones de los drivers de mi tarjeta para forzar un poco mas los fps al programa, entre ellos el antialiasing, que lo puse a 2x y resulta que eso me anulaba el z-buffer en el programa. Deberia ocurrir tal cosa o es pirada de olla de mis drivers? :blink:

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.