Jump to content

D3D > How to make the background transparent?


Recommended Posts

Hi,

I've successfully tested D3D examples and it's a very good work ;)

I've seen that the background is white by default, so I would like to know if it's possible to make it transparent?

e.g: for the "Cube" example of "(1) Vertex and Index Buffers"

FireFox.

Edited by FireFox
Link to comment
Share on other sites

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include "D3D9.au3"

Opt("GUIOnEventMode", 1)
Opt("MustDeclareVars", 1)

If Not IsDeclared("WM_DWMCOMPOSITIonchangeD") Then Global Const $WM_DWMCOMPOSITIonchangeD = 0x031E

Global Const $iWidth = 640, $iHeight = 480
; xyz and diffuse (color) vertex format
Global Const $FVF_Vertex = BitOR($D3DFVF_XYZ, $D3DFVF_DIFFUSE)

Local $hGUI = GUICreate("Direct3D9 (Test)", $iWidth, $iHeight, -1, -1, $WS_POPUP)

Local $pDevice, $oDevice
; Vertex and index buffers that hold the cube vertices and indices, respectively
Local $pCubeVB, $oCubeVB, $pCubeIB, $oCubeIB

_GDIPlus_Startup()
_D3D_Startup()

; Check if failed to load necessary dlls
If @error Then
    If @error = 1 Then
        Exit MsgBox(0x10, "Error", 'Could not load "d3d9.dll"')
    Else
        Exit MsgBox(0x10, "Error", 'Could not load "d3dx9_36.dll"')
    EndIf
EndIf

; Request a device that is to be associated with our window
$pDevice = _D3D_Init($hGUI, $iWidth, $iHeight)
$oDevice = _AutoItObject_WrapperCreate($pDevice, $tagID3DDevice9Interface)

; Setup rendering states and define our triangle's vertices
_Setup()

GUIRegisterMsg($WM_DWMCOMPOSITIonchangeD, "_WM_DWMCOMPOSITIonchangeD")
GUISetState()

_SendMessage($hGUI, $WM_DWMCOMPOSITIonchangeD)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Quit")
OnAutoItExitRegister("_Cleanup")
GUISetState()

While 1
    _Renderer()
    _HighPrecisionSleep(8000)
WEnd

Func _WM_DWMCOMPOSITIonchangeD($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tMargs = DllStructCreate($tagMARGINS)

    If _WinAPI_DwmIsCompositionEnabled() Then
        For $i = 1 To 4
            DllStructSetData($tMargs, $i, -1)
        Next
        _WinAPI_DwmExtendFrameIntoClientArea($hWnd, $tMargs)
    EndIf

    Return 0
EndFunc

Func _Renderer()
    ; static variables that hold the x and y rotation value in radians
    Local Static $nX, $nY

    ; matrices that represent the rotations
    Local $tXRot, $tYRot, $tWorld

    $tXRot = _D3DX_MatrixRotationX($nX)
    $tYRot = _D3DX_MatrixRotationY($nY)
    $tWorld = _D3DX_MatrixMultiply(DllStructGetPtr($tXRot), DllStructGetPtr($tYRot))

    ; Set device world transformation
    $oDevice.SetTransform("long", "int", $D3DTS_WORLD, "ptr", Number(DllStructGetPtr($tWorld)))

    ; update rotation variables
    $nY += 0.02
    $nX += 0.02

    ; if greater than or equals 2PI radians set to zero
    If $nX >= 6.28 Then $nX = 0
    If $nY >= 6.28 Then $nY = 0

    ; Draw the scene, clear the depth and back buffers
    $oDevice.Clear("long", "uint", 0, "ptr", 0, "uint", BitOR($D3DCLEAR_TARGET, $D3DCLEAR_ZBUFFER), "uint", 0, "float", 1, "uint", 0)
    $oDevice.BeginScene("long")

    ; Set the cube vertex buffer as the source for the primitives drawing
    $oDevice.SetStreamSource("long", "uint", 0, "ptr", Number($pCubeVB), "uint", 0, "uint", 16) ; our vertex structure size
    ; Set the cube index buffer that defines how each vertex gets mapped
    $oDevice.SetIndices("long", "ptr", Number($pCubeIB))
    ; Set the FVF that defines the cube's vertex format
    $oDevice.SetFVF("long", "uint", $FVF_Vertex)

    ; Draw an indexed primitive by specifying the number of vertices and triangles
    $oDevice.DrawIndexedPrimitive("long", "int", $D3DPT_TRIANGLELIST, "uint", 0, "uint", 0, "uint", 8, "uint", 0, "uint", 12)

    $oDevice.EndScene("long")
    $oDevice.Present("long", "ptr", 0, "ptr", 0, "hwnd", 0, "ptr", 0)
EndFunc

Func _Setup()
    Local $aResult, $tCubeVB, $pCubeVBPtr, $tCubeIB, $tPos, $tAt, $tUp, $tView, $tProj

    ; Cube coordinates, 3D cube contains 8 vertices
    Local $aCubeVB[8][4] = _
        [[ -1, -1, -1, 0xFFFF0000 ], _
         [ -1,  1, -1, 0xFF00FF00 ], _
         [  1,  1, -1, 0xFF0000FF ], _
         [  1, -1, -1, 0xFFFF0000 ], _
         [ -1, -1,  1, 0xFF00FF00 ], _
         [ -1,  1,  1, 0xFF0000FF ], _
         [  1,  1,  1, 0xFFFF0000 ], _
         [  1, -1,  1, 0xFF00FF00 ]]

    ; The index buffer maps each vertex to form a triangle (3 vertices per triangle, we have 12 triangles)
    ; The winding order defines whether a triangle is facing the camera or not (thus culled away)
    ; Clockwise triangles, with the default culling mode, face the camera and thus continue to next stages of processing
    ; Counter-clockwise triangles get culled and don't get it to next stages of processing.
    ; This is impormant as it saves processing time for the visible content of the scene.
    Local  $aCubeIB[36] = [ _
        0, 1, 2, _ ; front
        0, 2, 3, _
        4, 6, 5, _ ; back
        4, 7, 6, _
        4, 5, 1, _ ; left
        4, 1, 0, _
        3, 2, 6, _ ; right
        3, 6, 7, _
        1, 5, 6, _ ; top
        1, 6, 2, _
        4, 0, 3, _ ; bottom
        4, 3, 7  ]

    ; Create and define the cube vertex and index buffers
    $aResult = $oDevice.CreateVertexBuffer("long", "uint", 8 * 16, "uint", $D3DUSAGE_WRITEONLY, "uint", $FVF_Vertex, "int", $D3DPOOL_MANAGED, "ptr*", 0, "ptr", 0)
    $pCubeVB = $aResult[6]
    ; 36 indices times sizeof(WORD) -> 36 * 2 = 72
    $aResult = $oDevice.CreateIndexBuffer("long", "uint", 72, "uint", $D3DUSAGE_WRITEONLY, "int", $D3DFMT_INDEX16, "int", $D3DPOOL_MANAGED, "ptr*", 0, "ptr", 0)
    $pCubeIB = $aResult[6]

    $oCubeVB = _AutoItObject_WrapperCreate($pCubeVB, $tagIDirect3DVertexBuffer9)
    $oCubeIB = _AutoItObject_WrapperCreate($pCubeIB, $tagIDirect3DIndexBuffer9)

    ; Lock the entire vertex buffer to get a pointer to memory
    $aResult = $oCubeVB.Lock("long", "uint", 0, "uint", 0, "ptr*", 0, "uint", 0)
    $pCubeVBPtr = $aResult[4]

    For $i = 0 To 7
        $tCubeVB = DllStructCreate("float;float;float;uint", $pCubeVBPtr)

        For $j = 0 To 3
            DllStructSetData($tCubeVB, $j+1, $aCubeVB[$i][$j])
        Next

        $pCubeVBPtr += 16 ; our vertex structure size
    Next

    ; Unlock the vertex buffer
    $oCubeVB.Unlock("long")

    ; Lock the entire index buffer to get a pointer to memory
    $aResult = $oCubeIB.Lock("long", "uint", 0, "uint", 0, "ptr*", 0, "uint", 0)
    ; Create dllstrcut from memory pointer. Required size is 36 WORDs. 6 sides * 2 triangles per side * 3 vertices per triangle = 6 * 2 * 3 = 36
    $tCubeIB = DllStructCreate("word[36]", $aResult[4])

    For $i = 0 To 35
        DllStructSetData($tCubeIB, 1, $aCubeIB[$i], $i+1)
    Next

    ; Unlock the index buffer
    $oCubeIB.Unlock("long")

    ; Disable lighting as our vertices don't specify normals
    $oDevice.SetRenderState("long", "int", $D3DRS_LIGHTING, "bool", False)

    ; Set the view matrix, let the camera look down the positive z-axis
    ; camera position
    $tPos = _D3D_CreateVector3(0, 0, -5)
    ; camera targets the origin
    $tAt  = _D3D_CreateVector3(0, 0, 0)
    ; camera's up vector
    $tUp = _D3D_CreateVector3(0, 1, 0)

    $tView = _D3DX_MatrixLookAtLH(DllStructGetPtr($tPos), DllStructGetPtr($tAt), DllStructGetPtr($tUp))

    ; Set view matrix
    $oDevice.SetTransform("long", "int", $D3DTS_VIEW, "ptr", Number(DllStructGetPtr($tView)))

    ; Set projection matrix, let the frustum volume or FOV (field of view) be 90 degrees, in radians
    $tProj = _D3DX_MatrixPerspectiveFovLH(ASin(1), $iWidth/$iHeight, 1, 1000)
    $oDevice.SetTransform("long", "int", $D3DTS_PROJECTION, "ptr", Number(DllStructGetPtr($tProj)))
EndFunc

Func _Quit()
    Exit
EndFunc

Func _Cleanup()
    $oCubeIB = 0
    $oCubeVB = 0
    $oDevice = 0
    GUIDelete()
    _D3D_Shutdown()
    _GDIPlus_Shutdown()
EndFunc

; #FUNCTION#;===============================================================================
;
; Name...........: _HighPrecisionSleep()
; Description ...: Sleeps down to 0.1 microseconds
; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
; Parameters ....:  $iMicroSeconds      - Amount of microseconds to sleep
;                  $hDll  - Can be supplied so the UDF doesn't have to re-open the dll all the time.
; Return values .: None
; Author ........: Andreas Karlsson (monoceres)
; Modified.......:
; Remarks .......: Even though this has high precision you need to take into consideration that it will take some time for autoit to call the function.
; Related .......:
; Link ..........;
; Example .......; No
;
;;==========================================================================================
Func _HighPrecisionSleep($iMicroSeconds,$hDll=False)
    Local $hStruct, $bLoaded
    If Not $hDll Then
        $hDll=DllOpen("ntdll.dll")
        $bLoaded=True
    EndIf
    $hStruct=DllStructCreate("int64 time;")
    DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10))
    DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))
    If $bLoaded Then DllClose($hDll)
EndFunc

Func _WinAPI_DwmExtendFrameIntoClientArea($hWnd, ByRef $tMargins)
    Local $aResult = DllCall("dwmapi.dll", "int", "DwmExtendFrameIntoClientArea", "hwnd", $hWnd, "ptr", DllStructGetPtr($tMargins))

    If @error Then Return SetError(@error, @extended, -1)
    Return $aResult[0]
EndFunc

Func _WinAPI_DwmIsCompositionEnabled()
    Local $aResult = DllCall("dwmapi.dll", "int", "DwmIsCompositionEnabled", "int*", 0)

    If @error Then Return SetError(@error, @extended, -1)
    Return SetError($aResult[0], 0, $aResult[1])
EndFunc

Cool, isn't it? ;]

Link to comment
Share on other sites

If you're running windows Vista, then make sure composition is enabled. If you're

using XP or other Windows OS that doesn't support the new Aero-Glass theme

it's too bad. You'll need to Google for some Direct3D examples about how to

screen-shot the surface of the desktop, then render the content to your back

buffer and apply the shapes drawing after. It's an ugly hack and code.

@trancexx:

At first I've handled the WM_ERASEBKGND notification and used GDI+ to fill

the background with black brush. It isn't needed, just a leftover.

Link to comment
Share on other sites

If you're running windows Vista, then make sure composition is enabled. If you're

using XP or other Windows OS that doesn't support the new Aero-Glass theme

it's too bad. You'll need to Google for some Direct3D examples about how to

screen-shot the surface of the desktop, then render the content to your back

buffer and apply the shapes drawing after. It's an ugly hack and code.

@trancexx:

At first I've handled the WM_ERASEBKGND notification and used GDI+ to fill

the background with black brush. It isn't needed, just a leftover.

Yeah I think you're right, I've aero disabled but I'm not able to re-activate it...

I will re-install win7 anyway ;)

Edit: Solved, Impressive! Posted Image

Br, FireFox.

Edited by FireFox
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...