Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Error! Visual Basic 6 (Directx 8)

Iniciado por •Parra, 02 de Junio de 2009, 09:52:19 PM

« anterior - próximo »

•Parra

Buenas! Estaba buscando un foro como este.. donde tubieran programación grafica y me pudieran ayudar.. y me acabo de registrar!

Ya se que visual basic 6 es uno de los peores lenguajes.. u_u pero bueno, algo bueno podré hacer con él ^^

Mi problema es..
estoy haciendo un motor isometrico.. hice la carga de texturas.. todo perfecto, tambien hice que calculara los cuadrados de diferentes perspectivas isométricas.. etc.. por ahora el motor beta está todo bien.. excepto mi error..

Yo uso de esta forma las funciones para limpiar la pantalla, y hacer .present:

Código (vb) [Seleccionar]
Private Sub deviceBeginScene()
   
    With D3DDevice
       
        If (eWindowed = True) Then
            .Clear 1, DirectxRect, D3DCLEAR_TARGET, 0, 1#, 0
        Else
            .Clear 0, ByVal 0&, D3DCLEAR_TARGET, 0, 1#, 0
        End If
       
        .BeginScene
    End With
   
End Sub
Private Sub deviceEndScene()

    With D3DDevice
       
        .EndScene
   
        If (eWindowed = True) Then
            .Present RenderRect, RenderRect, frmMain.hwnd, ByVal 0
        Else
            .Present ByVal 0&, ByVal 0&, frmMain.hwnd, ByVal 0&
        End If

    End With
   
End Sub


El .clear me funciona perfectamente en full screen y windowed.. pero el .present, me da error en modo windowed.. me da error de automatización.. y no lo he podido arreglar.. he probado jugando bastante.. y nada.. siempre el mismo error..

entonces.. envez de usar esa forma que tengo arriba.. me gutaria usar el modo de full screen para los dos modos sin que me de error.. hay alguna posibilidad? porque me da este error?

Gracias a todos los interesados en ayudar ;)

edit: aclaro.. el error me lo da cuando le doy al debugger..

la iniciación del directx la tengo asi:
Código (vb) [Seleccionar]
Public Function engineInitializing(ByRef Top As Integer, ByRef Left As Integer, ByRef Width As Integer, ByRef Height As Integer, Frm As Form, Optional ByRef BitsPerPixel As Byte = 32, Optional ByRef Windowed As Boolean = True) As Boolean

On Error GoTo ErrHandle
   
    Set DX = New DirectX8
    Set D3D = DX.Direct3DCreate
    Set D3DX = New D3DX8
   
    eWindowed = Windowed
   
    With RenderRect
        .Top = Top
        .Left = Left
        .Right = Width
        .bottom = Height
    End With
   
    With DirectxRect
        .X1 = Left
        .X2 = Width
        .Y1 = Top
        .Y2 = Height
    End With
   
    '*******************************
    'Initialize video device
    '*******************************
    Dim DevType As CONST_D3DDEVTYPE
    Dim D3DCreate As CONST_D3DCREATEFLAGS
   
    DevType = D3DDEVTYPE_HAL

    D3D.GetDeviceCaps D3DADAPTER_DEFAULT, DevType, DevCaps
    D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, DispMode
   
    With D3DWindow
   
        If (Windowed = False) Then
       
            .SwapEffect = D3DSWAPEFFECT_FLIP
            .FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT
            .FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE
           
            'Fullscreen mode stuff here
            Select Case BitsPerPixel
                Case 32
                    .BackBufferFormat = D3DFMT_A8R8G8B8
                Case 24
                    .BackBufferFormat = D3DFMT_R8G8B8
                Case 16
                    .BackBufferFormat = D3DFMT_R5G6B5
                Case Else
                    .BackBufferFormat = D3DFMT_A8R8G8B8
            End Select
           
            .BackBufferWidth = 800
            .BackBufferHeight = 600

            .BackBufferCount = 1
        Else
            .Windowed = 1
            .SwapEffect = D3DSWAPEFFECT_COPY
            .BackBufferFormat = DispMode.Format
        End If
       
        .hDeviceWindow = Frm.hwnd
       
    End With
   
       
    'To check the rest we use:
    If Not D3D.CheckDeviceType(D3DADAPTER_DEFAULT, DevType, DispMode.Format, DispMode.Format, 1) = D3D_OK Then
        DevType = D3DDEVTYPE_REF
    ElseIf Not D3D.CheckDeviceType(D3DADAPTER_DEFAULT, DevType, DispMode.Format, DispMode.Format, 1) = D3D_OK Then
        DevType = D3DDEVTYPE_SW
    End If
   
    'For Hardware vertex processing:
    If Not (DevCaps.DevCaps And D3DDEVCAPS_HWTRANSFORMANDLIGHT) Then
        D3DCreate = D3DCREATE_SOFTWARE_VERTEXPROCESSING
    Else
        D3DCreate = D3DCREATE_HARDWARE_VERTEXPROCESSING
    End If
   
    'Set the D3DDevices
    If Not D3DDevice Is Nothing Then Set D3DDevice = Nothing
    Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, DevType, Frm.hwnd, D3DCreate, D3DWindow)
   
    'Reset the device's rendering state
    deviceResetRenderStates

    fontInitializing (GetVar(App.Path & "\Init\Fonts.ini", "Info", "Size"))
   
    'Clear the back buffer
    D3DDevice.Clear 0, ByVal 0&, D3DCLEAR_TARGET, 0, 0, 0
   
    'Initialize DB
    If (texInitialize() = False) Then GoTo ErrHandle
   
    'Initialize Index
    loadGrh
   
    engineInitializing = True
    Exit Function
   
ErrHandle:
    MsgBox "Error al iniciar el motor grafico"
    engineInitializing = False
End Function


[EX3]

Cita de: •Parra en 02 de Junio de 2009, 09:52:19 PM
Ya se que visual basic 6 es uno de los peores lenguajes.. u_u pero bueno, algo bueno podré hacer con él ^^
Me lo vas a contar a mi :P

Lo primero, si te empeñas en programar a pelo con DirectX, visita el sitio DirectX4VB. Alli encontaras tutoriales a tutiplen sobre DirectX8 en VB6.0.

Lo segundo, si te animas, te recomiendo que eches un vistazo a mi libreria y asi pases de pegarte con DirectX y perder tiempo acondicionando tu motor a su API. dx_lib32 hace de puente entre DirectX y VB6.0 simplificando muchas tareas comunes en cuanto a graficos, audio, input, video y mas cosas que te pueden servir de ayuda. No es una maravilla en ciertos aspectos pero seguro que te ahorra trabajo para rato, sobre todo con errores como este.

Respondiendo a tu post, yo en mi codigo de render solo tengo una llamada a Clear() y Present() para ventana y pantalla completa ya que ambas sirven por igual. El fallo quizas lo tengas por introducir el parametro RenderRect en la llamada a Present(). El metodo si mal no recuerdo por la documentacion no permite mas parametros que el color de fondo con el que se borrara el buffer y el hwnd de la ventana. Los otros parametros deben ir a 0. En resumen, la misma llamada a Present() en pantalla completa te de funcionar en modo ventana. Prueba y me cuentas.

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

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

•Parra

Si, es verdad, me funciona perfectamente, pero el problema que tengo es que no le puedo poner que haga .present solo en una zona.. debo de hacer .present en toda la pantalla y eso es lo que no quiero hacer

alguna solución?

PD: estaba buscando tu email.. y vi que eres moderador de aqui..
he visto tu dll tambien, pero prefiero hacer mi motor.. ya que tengo varios diferentes armados.. y las bases son buenas..

la web que mencionaste ya la conocia.. la usé sobre todo cuando estube jugando con dx7..

otra cosa.. como reproduces en tu dll los mp3? usas la api de windows?

[EX3]

Lo de realizar varios Present() en distintas partes de la pantalla, no se si te refieres a crear un sistema de DirtyRects o similar, pero creo que esa funcionalidad (no me hagas mucho caso que aunque lo parezca no estoy tan puesto como me gustaria en materia :P) esta deshabilitado en las ultimas versiones de Direct3D, pero aun asi recuerdo algo sobre las SwapsChains que creo que es el sistema que implementa D3D8/9 para poder realizar varios renders al mismo tiempo, lo que no recuerdo si eso era para usar en un mismo contexto (una pantalla o ventana) o en varios (multiples pantallas o ventanas). Creo que mas bien lo segundo que lo primero.

Sobre lo de los MP3, al igual que para el video, utilizo DirectShow ya que este utiliza los codecs instalados en el sistema, incluidos codecs para OGG Vorbis que encontraras en las descargas de mi web. Para ello me base en este tutorial de DirectX4VB.

Cita de: •Parra en 03 de Junio de 2009, 03:23:15 PM
he visto tu dll tambien, pero prefiero hacer mi motor.. ya que tengo varios diferentes armados.. y las bases son buenas..
Tiene gracia, asi estoy desarrollando yo el motor de mi eterno proyecto juego, usando retales de intentos anteriores :D y es una lastima, dx_lib32 tiene una funcion de dibujo con proyecciones que seguro te vendria de perlas para tu render isometrico :)

Pues nada, suerte con el desarrollo del motor, y paciencia, VB 6.0 suele ser un poco tocapelotas con errores raros y excepciones de memoria a la hora de complicar el codigo en este tipo de desarrollos, sobre todo con algunas llamadas a la API de DirectX (Direct3D para ser mas concretos).

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

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

•Parra

#4
si! exactamente.. eso es.. DirtyRects.

Es lo que quiero hacer =/ pero no puedo.. gracias por toda la informacion sobre tu mp3..

entonces.. no tengo solución para hacer present en un rect? :(

edit: ah si.. acabo de ver el tutorial.. yo ya hice un programa tipo este.. fué facil.. el problema que me encontré fue.. que necesito reproducir distintos mp3 a la vez.. y no pude hacerlo.. =/

el otro problema.. aunque es una tonteria.. es el molesto iconzito.. que te sale cada vez que reproduces algo..

edit2: el unico remedio que veo contra eso.. si no puedo arreglar.. seria hacer un modulo como este:

Código (vb) [Seleccionar]
Option Explicit

'Module to management textures(GUI)

Private Type structGUI
    Tex     As Direct3DTexture8
    Path    As String
    Width   As Integer
    Height  As Integer
   
    vert(3) As TLVERTEX
End Type
   
Private Texture() As structGUI

Public Function GuiInitialize() As Boolean
On Error GoTo ErrHandle
    Dim i As Long

    ReDim Preserve Texture(1 To 1) As structGUI
   
    'Provisional
    Texture(1).Path = "\Graphics\frmmain.jpg"
    Texture(1).Width = 800
    Texture(1).Height = 600
   
    For i = 1 To UBound(Texture)
        If GuiLoadTexture(i) = False Then GoTo ErrHandle
        GuiSetGeometry (i)
    Next i

    GuiInitialize = True
    Exit Function
   
ErrHandle:
    GuiInitialize = False
    Exit Function
End Function

Private Function GuiLoadTexture(ByRef Index As Long) As Boolean
On Error GoTo ErrHandle

    With Texture(Index)
        Set .Tex = D3DX.CreateTextureFromFileEx(D3DDevice, _
                            App.Path & .Path, .Width, .Height, _
                            D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, _
                            D3DPOOL_MANAGED, D3DX_FILTER_POINT, _
                            D3DX_FILTER_POINT, D3DColorXRGB(255, 0, 128), _
                            ByVal 0, ByVal 0)
    End With
   
    GuiLoadTexture = True
    Exit Function
   
ErrHandle:
    GuiLoadTexture = False
End Function
Private Sub GuiSetGeometry(ByRef Index As Long)
    With Texture(Index)
        .vert(0) = setVertex(0, 0, 0, 1, -1, 0, 0, 0)
        .vert(1) = setVertex(CSng(.Width), 0, 0, 1, -1, 0, 1, 0)
        .vert(2) = setVertex(0, CSng(.Height), 0, 1, -1, 0, 0, 1)
        .vert(3) = setVertex(CSng(.Width), CSng(.Height), 0, 1, -1, 0, 1, 1)
    End With
End Sub
Public Sub GuiDelete()

    Dim i As Long
   
    For i = 1 To UBound(Texture)
        Set Texture(i).Tex = Nothing
    Next i
   
End Sub
Public Sub GuiRender()

    If (testCooperative = False) Then Exit Sub

    Dim i As Long

    For i = 1 To UBound(Texture)
        If Texture(i).Tex Is Nothing Then
            If (GuiLoadTexture(i) = False) Then Exit Sub
        End If
       
        With D3DDevice
         .Clear 0, ByVal 0&, D3DCLEAR_TARGET, 0, 1#, 0
            .BeginScene
           
            .SetTexture 0, Texture(i).Tex
            .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, Texture(i).vert(0), Len(Texture(i).vert(0))
           
            .EndScene
         .Present ByVal 0&, ByVal 0&, frmMain.hwnd, ByVal 0&
        End With
    Next i
   
End Sub


aunque no me convence demasiado.. renderizar texturas de 800x600 es mortal..

[EX3]

#5
Cita de: •Parra en 03 de Junio de 2009, 06:06:09 PM
edit: ah si.. acabo de ver el tutorial.. yo ya hice un programa tipo este.. fué facil.. el problema que me encontré fue.. que necesito reproducir distintos mp3 a la vez.. y no pude hacerlo.. =/
El codigo del tutorial se puede aplicar de forma aislada, como un objeto independiente, y reproducir tantos mp3 como quieras. Yo de por si tengo implementado reproduccion dual en dx_lib32 para poder implementar fades entre dos musicas.

Cita de: •Parra en 03 de Junio de 2009, 06:06:09 PM
el otro problema.. aunque es una tonteria.. es el molesto iconzito.. que te sale cada vez que reproduces algo..
A mi no me aparece ningun icono al reproducir audio con DirectShow, pero si es cierto que el otro dia en el ordenador de la oficina me salto la ventana de configuracion del codec ffdshow ya que tiene instalado el K-Lite CodePack, pero solo salio una vez, no ha vuelto a salir. Aun asi debe tener alguna forma de evitar eso. Si no, te tocaria tirar de librerias como FMod para el tema de musica sin pasar por los codecs de DirectShow.

Cita de: •Parra en 03 de Junio de 2009, 06:06:09 PM
aunque no me convence demasiado.. renderizar texturas de 800x600 es mortal..
Por? A mi no me da problemas renderizar texturas grandes, me da problemas, tal y como lo tengo implementado (y creo que lo tienes igual) el pintar un numero alto de sprites, sin importar el tamaño, ya que pinto cada uno como una llamada independiente en vez de agruparlos en un vertexBuffer o similar, que lograria mas rendimiento al dibujar todo en una llamada (aunque para mi al menos es mas complicado de programar). Seria similar a dibujar una malla de poligonos.

Salu2...

Edit:
Código (vbnet) [Seleccionar]
For i = 1 To UBound(Texture)
        If Texture(i).Tex Is Nothing Then
            If (GuiLoadTexture(i) = False) Then Exit Sub
        End If

        With D3DDevice
         .Clear 0, ByVal 0&, D3DCLEAR_TARGET, 0, 1#, 0
            .BeginScene

            .SetTexture 0, Texture(i).Tex
            .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, Texture(i).vert(0), Len(Texture(i).vert(0))

            .EndScene
         .Present ByVal 0&, ByVal 0&, frmMain.hwnd, ByVal 0&
        End With
    Next i

Estas haciendo un present por cada textura que pintas?  8o Solo necesitas llamar una sola vez a present y clear, justo cuando hayas pintado toda la escena, no en cada llamada a DrawPrimitiveUP. Lo mismo con BeginScene y EndScene. Asi si que baja el rendimiento por los suelos, es como si estuvieras dibujando varias escenas una sobre otra  ^_^' En dx_lib32, salvo que uses RenderTarget, solo llama una vez a BeginScene y EndScene, justo antes y despues de llamar a Clear y Present en la funcion de Render.
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

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

•Parra

eso lo hice pensando en actualizar independientemente cuando necesitara actualizar las interfaces.. pero es todo un lio increible.. solo solucionando lo de RECT en .persent me bastaria!

tu tienes lo de los rects implementados en tu libreria? si es asi.. me sabrias decir porque tengo ese error? =/

[EX3]

No entiendo lo del lio. Teniendo bien estructurado el codigo seria simplemente llamar a Clear y Present justo al final del bucle principal:

bucle
{
    // Todas las llamadas graficas que se hagan en la escena:
    ...
    dibujar textura
    dibujar textura
    dibujar textura
    ...

    // Enviamos las escena a la tarjeta grafica para renderizarse:
    present
    clear
}

Yo lo de los dirtyrect lo olvidaria ya que te vas a complicar mas que otra cosa. Yo implemente nada de DirtyRects, simplemente intente descartar el numero posible de llamadas redundantes, como por ejemplo configurar la misma textura varias veces o aplicar el mismo estado en la textura haciendolo solo una vez. Ten encuenta que D3D8 no es un API 2D y por lo tanto no se comporta igual a la hora de aplicar ciertas tecnicas que si son validas en API's 2D. En 3D lo optimo es agrupar elementos comunes, por ejemplo, los sprites, lo suyo seria poder agruparlos por textura y estados del render por ejemplo, que suelen ser operaciones muy costosas. Agrupas y envias toda la geometria con una sola llamada. Dado que lo estas implementando por el mismo camino que yo hice en su dia, te interesa complicarte lo minimo posible la estructura del motor. Lo suyo seria que hicieras una estructura secuencial como la de arriba. Tus funciones de dibujo u objetos sprite configuren la textura y sus estados y llamen a DrawPrimitiveUP y al final del todo tener preparado un metodo Render() que haga la llamada a Present() y Clear().

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

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

•Parra

#8
listo!! ya lo arreglé.. era todo culpa del spaweffect :P

muchas gracias por interesarse.. y por los consejos.. saludos! (pueden cerrar..)

[EX3]

Pues nada, ya nos contaras que tal tus andaduras con VB6.0, DX8 y tu motor isometrico :)

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

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

•Parra

ok, cuando vaya haciendo el mapeado.. postearé alguna imagen ;)






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.