OGI's picture

MD2 render custom color depth

Hi guys,
I'm working on a simple 2D game engine and by now the only thing that left to be done is the characters animation system. Everything is 2D except the characters, for them I'm using MD2 models and a standard OpenTK render with inherited GameWindow. OpenTK render crashes because the screen is controlled by DirectDraw and all the graphics are displayed using DirectDraw which sets the screen color depth to 16bit by default which is lower than OpenTK render color depth. If I set the DirectDraw display mode to 32bit everything works fine. But I want to give the users the freedom to choose between different color depths. So my question is do you know how to change OpenTK render color depth?

The engine is written on VB .NET 2010 and C#.

I'm pretty new at OpenGL and in 3D graphics programming at all, so it's little hard for me to understand all the C++ stuff in the web about this problem, C# and especially VB .NET examples are very rare :( Thank you in advance!

Here is the 3D characters class with the renderer:

Imports OpenTK
Imports OpenTK.Graphics
Imports OpenTK.Graphics.OpenGL
 
Public Class VisualObject
 
Inherits GameWindow
 
#Region "MD2Render"
 
#Region "Public Variables"
    Public sngYawPlus As Single = 5.0F 'use this var for nonstop rotate
    Public szeSurface As Size = New Size(80, 128) '34x73
    Public bmpTransfer As New Bitmap(szeSurface.Width, szeSurface.Height)
    Public bmpFace As New Bitmap(szeSurface.Width, szeSurface.Height)
#End Region
 
#Region "Private Variables"
    Private WithEvents tmrRend As New Windows.Forms.Timer
    Private tmrTick As New System.Diagnostics.Stopwatch
    Private md2Model() As Q2MD2Model
    Private yaw As Single
    Private bd As System.Drawing.Imaging.BitmapData
#End Region
 
    Private Sub tmrRendTick(sender As Object, e As System.EventArgs) Handles tmrRend.Tick
        Try
            RendFrame()
        Catch ex As Exception
            tmrRend.Stop()
        End Try
    End Sub
 
    Public Sub StartRend()
        tmrTick.Start()
        tmrRend.Start()
    End Sub
 
    Public Sub StopRend()
        tmrTick.Stop()
        tmrRend.Stop()
    End Sub
 
'get bitmap from the renderer:
    Public Sub GetFrame()
        If GraphicsContext.CurrentContext Is Nothing Then
            Exit Sub
        End If
 
        bd = bmpTransfer.LockBits(New Rectangle(0, 0, szeSurface.Width, szeSurface.Height),
            System.Drawing.Imaging.ImageLockMode.[WriteOnly],
            System.Drawing.Imaging.PixelFormat.Format24bppRgb)
 
        GL.ReadPixels(0, 0, szeSurface.Width, szeSurface.Height,
                      OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, bd.Scan0)
 
        bmpTransfer.UnlockBits(bd)
        bmpTransfer.RotateFlip(RotateFlipType.RotateNoneFlipY)
        bmpTransfer.MakeTransparent()
        bmpFace = bmpTransfer
    End Sub
 
 
    Private Sub RendFrame()
        GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit)
        GL.MatrixMode(MatrixMode.Modelview)
        GL.LoadIdentity()
 
        GL.Translate(0, 0, -17) 'model position
        GL.Rotate(45, 1, 0, 0) 'viepoint angle, default(45, 1, 0, 0) = ~45 degrees 
 
        'GL.Rotate(yaw, 0, 1, 0) 'use this var for nonstop rotate
        'yaw += sngYawPlus 'use this var for nonstop rotate
 
        GL.Rotate(Cursor.Position.Y, 0, 1, 0) 'custom rotation - from 0 to 360(full rotation)
 
        'rend body parts:
        For i = 0 To UBound(md2Model)
            md2Model(i).Render(tmrTick.ElapsedMilliseconds)
        Next
 
        SwapBuffers()
 
        GetFrame()
    End Sub
#End Region
 
#Region "Initializations"
    'the constructor:
    Public Sub New()
        tmrMoveAI.Interval = 1
        GL.Enable(EnableCap.DepthTest)
        GL.ClearColor(Color4.Black)
        'GL.ClearColor(1.0, 0.0, 1.0, 0.0) 'fuschia
        GL.Enable(EnableCap.Texture2D)
 
        ReDim md2Model(0)
        md2Model(0) = New Q2MD2Model(strDefDir & "RES\units\tris.md2", "RES\units\t.bmp", 0.23)
        tmrRend.Interval = 100
 
        Dim mat As Matrix4 = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 1, 0.1, 1000)
        GL.Viewport(0, 0, szeSurface.Width, szeSurface.Height)
        GL.MatrixMode(MatrixMode.Projection)
        GL.LoadMatrix(mat)
        GL.MatrixMode(MatrixMode.Modelview)
        GL.LoadIdentity()
        'md2Model(0).SetAnimation(0, 10, 100, 0)
 
        StartRend()
    End Sub
#End Region
 
End Class

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

In your VisualObject constructor, call the base GameWindow constructor with a custom GraphicsMode:

#Region "Initializations"
    'the constructor:
    Public Sub New()
        Me.New(800, 600, New GraphicsMode(32, 24, 8))
        ...

(I haven't used VB.Net for ages, I hope the syntax is correct)

OGI's picture

Thank you for the fast reply but I tried this before it just doesn't work, it says:
"Constructor Public Sub New() cannot call itself"
Maybe I don't make the constructor call correct? :(

the Fiddler's picture

You need to call the base constructor of the GameWindow. No idea what the syntax is in VB, sorry. (Try replacing Me.New with Base.New or some such.)

OGI's picture

I wasn't on my computer for a while, thank you for the help, it seems that MyBase.New statement is the correct expression, I've done it this way:

MyBase.New(800, 600, New GraphicsMode(16, 16, 8, 4))

But now the textures of my models are gone, instead I have brick-red colored silhouettes. Do you know where I make things wrong?

the Fiddler's picture

Try using 32bit for color, i.e. New GraphicsMode(32, 16, 8, 4). The only reason to use 16bit is when running on pre-Geforce GPUs (Riva TNTs and the like).

That said, there's something strange going on with 16bit color modes. I'm also getting brick-red silhouettes when using 16bit on my Nvidia/Windows system, but not when using a virtual machine on the same system. Need to investigate.

OGI's picture

Well that's interesting... as far as I know GraphicsMode(32, 24, 8, 4) means graphics context with 32bpp color, 24bpp depth, 8bpp stencil and 4x anti-aliasing. In my project I don't need anti-aliasing, so I guess setting the value to 0 will turn it off an lead to better performance?
Thank you for the suggestion I tried GraphicsMode(32, 16, 8, 4) and the textures are visible again(no brick color). I'm looking forward for the results from your tests, thanks again :)

the Fiddler's picture

Indeed, if you don't need antialiasing then turning it off will improve performance. GraphicsMode lets you specify the parameters that you need (e.g. antialiasing, stereoscopic rendering, etc). If a parameter is not supported, it will fall back to the closest mode that matches or exceeds the parameters you specify.

If you don't need any specific parameters, GraphicsMode.Default will give you the mode with the highest compatibility (currently defined as (32, 16)).