RE: Dx9 Sprite Transform/Win7 Issue [solution]

Advanced game related topics
User avatar
Innesoft
Enthusiast
Enthusiast
Posts: 105
Joined: Mon Jan 18, 2010 10:30 am
Location: UK
Contact:

RE: Dx9 Sprite Transform/Win7 Issue [solution]

Post by Innesoft »

I deleted the old topic, because there's clearly no interest in the issue.. but it could cause big problems for people so I'm sharing the solution here.

In a nutshell:
If you use the "Disable Backface Culling" assembly trick to flip your 3D sprites with TranformSprite3D, this will not work reliably on windows 7. The result is missing sprites. The code floating around the forum is wrong and will cause this problem (some of which is from me.. so, guilty).

This is the wrong code...

Code: Select all

  ;Disable Backface Culling
  Define pd3d.IDirect3DDevice9
  Start3D()
  EnableASM
  !extrn _PB_Screen_Direct3DDevice
  !MOV dword EAX, [_PB_Screen_Direct3DDevice]
  !MOV dword [v_pd3d],EAX
  DisableASM
  pd3d\SetRenderState(22,1)
  Stop3D()

;0=No Flip, 1=Horiz, 2=Vert, 3=Both
Procedure TformSprite3D(SpriteID.l,scale.f=512,flipmode.i=0)
  Select flipmode.i
    Case 0
      TransformSprite3D(SpriteID,0,0,0,scale.f,0,0,scale.f,scale.f,0,0,scale.f,0)  
    Case 1
      TransformSprite3D(SpriteID,scale.f,0,0,0,0,0,0,scale.f,0,scale.f,scale.f,0)  
    Case 2
      TransformSprite3D(SpriteID,0,scale.f,0,scale.f,scale.f,0,scale.f,0,0,0,0,0)
    Case 3
      TransformSprite3D(SpriteID,scale.f,scale.f,0,0,scale.f,0,0,0,0,scale.f,0,0)  
  EndSelect
EndProcedure
This is the correct code, and will work on Windows7...

Code: Select all

  ;Disable Backface Culling
  Define pd3d.IDirect3DDevice9
  Start3D()
  EnableASM
  !extrn _PB_Screen_Direct3DDevice
  !MOV dword EAX, [_PB_Screen_Direct3DDevice]
  !MOV dword [v_pd3d],EAX
  DisableASM
  pd3d\SetRenderState(22,1)
  pd3d\SetRenderState(7,0)
  Stop3D()

;0=No Flip, 1=Horiz, 2=Vert, 3=Both
Procedure TformSprite3D(SpriteID.l,scale.f=512,flipmode.i=0)
  z.f=1.0
  Select flipmode.i
    Case 0
      TransformSprite3D(SpriteID,0,0,z.f,scale.f,0,z.f,scale.f,scale.f,z.f,0,scale.f,z.f)  
    Case 1
      TransformSprite3D(SpriteID,scale.f,0,z.f,0,0,z.f,0,scale.f,z.f,scale.f,scale.f,z.f)  
    Case 2
      TransformSprite3D(SpriteID,0,scale.f,z.f,scale.f,scale.f,z.f,scale.f,0,z.f,0,0,z.f)
    Case 3
      TransformSprite3D(SpriteID,scale.f,scale.f,z.f,0,scale.f,z.f,0,0,z.f,scale.f,0,z.f)  
  EndSelect
EndProcedure
What's the difference?
pd3d\SetRenderState(22,1) uses the IDirect3DDevice9::SetRenderState TYPE of D3DRS_CULLMODE (22) and sets it to D3DCULL_NONE (1), disabling backface culling as you'd expect, but by default, the z-buffer is still taken into account even though you draw your sprite3D's in a set order. What was missing from the first code is..

Code: Select all

pd3d\SetRenderState(7,0)
..which sets D3DRS_ZENABLE (7) to D3DZB_FALSE (0), disabling the z-buffer. As an extra step, when making a transform for 2D-in-3D you should not set the z-value to 0, instead set it to 1.0 to avoid any chance of z-fighting with the background. On a flat sprite, z-values of 1.0 will look no different than z-values of 0.0.