Original Post
Hi everybody, I've been reading the book "OpenGl Game Developing" by Chris Seddon and translating the code to c# with Tao and I'm running into some troubles in Chapter 2 so I wanted to know if somebody could help me out a bit :D. When using the SimpleOpenglControl provided with the framework I had no problem (other than buggy graphics, but I believe that's because of the integrated video card), but when I try my own Initialization of OpenGL, It seems like it creates the contexts just fine but It won't draw in the Panel, so I believe it has something to do with the Raster class: Excuse the use of spanish comments, they were too many to translate. Ok, so In the form1 class I create an object of the Raster class, after the InitializeComponents() method has been called, I initialize some variables and call the Init(Control RenderTarget) method of the raster object giving it the panel(this instead of the SimpleOpenglControl InitializeContexts() Method). Then I force a change in the form size to call an event that will set the viewport and the ortho projection(this is called every time the window resizes). Finally in the Render method at the end I use the Gdi.SwapBuffers method giving it the DeviceContext from the raster object(Instead of the SimpleOpenGlControl SwapBuffers() method). Thanks to anybody who read all of this XD, any help is appreciated. [Edited by - crackers on February 19, 2008 10:00:15 AM]
class Raster
{
//Necesitamos Importar los metodos para obtener y liberar el
//Device Context
#region Importaciones
/// <summary>
/// IMporta el metodo GetDC(Intptr hWnd) del GDI
/// </summary>
/// <param name="hWnd">El handle de una ventana</param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "GetDC")]
public static extern IntPtr GetDC(IntPtr hWnd);
/// <summary>
/// Este importa el ReleaseDC que libera el dispositivo
/// </summary>
/// <param name="hWnd">El Handle de la ventana</param>
/// <param name="hDC">El dispositivo q se va a liberar</param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "ReleaseDC")]
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
#endregion
#region MiembrosPrivados
private Control _renderTarget;
private byte _colorBits;
private byte _depthBits;
//El tipo Intpts es para handles o para referencias
private IntPtr _handleDeviceContext;
private IntPtr _handleRenderContex;
#endregion
#region Propiedades
public byte ColorBits
{
set
{
_colorBits = value;
}
get
{
return _colorBits;
}
}
public byte DepthBits
{
set
{
_depthBits = value;
}
get
{
return _depthBits;
}
}
public IntPtr DeviceContext
{
set
{
_handleDeviceContext = value;
}
get
{
return _handleDeviceContext;
}
}
public IntPtr RenderContext
{
set
{
_handleRenderContex = value;
}
get
{
return _handleRenderContex;
}
}
#endregion
#region Constructor
/// <summary>
/// Inicializa varias cosas
/// </summary>
public Raster()
{
ColorBits = 24;
DepthBits = 32;
RenderContext = IntPtr.Zero;
DeviceContext = IntPtr.Zero;
}
#endregion
#region Metodos Publicos
/// <summary>
/// Inicializa OpenGl
/// </summary>
/// <returns>True si se inicializo, sino false</returns>
public bool Init(Control RenderTarget)
{
//Variables Locales
int pixelFormat;
Gdi.PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
//Paso de datos
_renderTarget = RenderTarget;
//Intentamos obtener el device context de la ventana
DeviceContext = GetDC(_renderTarget.Handle);
if (DeviceContext == IntPtr.Zero)
{
//y mostramos un mensaje de error si no se pudo
MessageBox.Show(_renderTarget, "No se pudo obtener el"
+ " Device Context para la ventana","Error"
,MessageBoxButtons.OK,MessageBoxIcon.Error);
_renderTarget = null;
return false;
}
//Se llena el pixelformatdescriptor y hacemos que el programa
//escoja un formato de pixeles adecuado
pixelFormatDescriptor = llenarPixelFormatDescriptor();
pixelFormat = Gdi.ChoosePixelFormat(DeviceContext, ref pixelFormatDescriptor);
if (pixelFormat == 0)
{
//Y chequiamos si se pudo o no
MessageBox.Show(_renderTarget, "No se pudo escoger un"
+ " Formato de pixeles", "Error"
,MessageBoxButtons.OK,MessageBoxIcon.Error);
ReleaseDC(_renderTarget.Handle, DeviceContext);
DeviceContext = IntPtr.Zero;
_renderTarget = null;
return false;
}
//Ñe decimos al programa que use ese formato de pixeles en la ventana
if (!Gdi._SetPixelFormat(DeviceContext, pixelFormat, ref pixelFormatDescriptor))
{
MessageBox.Show(_renderTarget, "No se pudo setear el"
+ " Formato de pixeles para la ventana", "Error"
,MessageBoxButtons.OK,MessageBoxIcon.Error);
ReleaseDC(_renderTarget.Handle, DeviceContext);
DeviceContext = IntPtr.Zero;
_renderTarget = null;
return false;
}
//Con el deveice context creamos un render context para el programa
RenderContext = Wgl.wglCreateContext(DeviceContext);
if (RenderContext == IntPtr.Zero)
{
MessageBox.Show(_renderTarget, "No se pudo obtener el"
+ " Render Context para la ventana", "Error"
, MessageBoxButtons.OK, MessageBoxIcon.Error);
ReleaseDC(_renderTarget.Handle, DeviceContext);
DeviceContext = IntPtr.Zero;
_renderTarget = null;
return false;
}
//Acemos que el thread que llama al metodo use el render context
//que creamos como su render context actual
if (!Wgl.wglMakeCurrent(DeviceContext, RenderContext))
{
MessageBox.Show(_renderTarget, "No se pudo obtener el"
+ " Render Context para la ventana", "Error"
, MessageBoxButtons.OK, MessageBoxIcon.Error);
Wgl.wglDeleteContext(RenderContext);
ReleaseDC(_renderTarget.Handle, DeviceContext);
RenderContext = IntPtr.Zero;
DeviceContext = IntPtr.Zero;
_renderTarget = null;
return false;
}
return true;
}
public bool Release()
{
//Revisa si se ha llamado al metodo init correctamente antes de liberar
//los recursos
if (RenderContext == IntPtr.Zero || DeviceContext == IntPtr.Zero)
{
MessageBox.Show("No esta inicializado");
return false;
}
//Dejamos de hacer que el thread use nuestro rendercontext para dibujar
if (!Wgl.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero))
{
MessageBox.Show(_renderTarget, "No se pudo liberar al DC y al RC",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
//Liberamos el Rendering Context
if (!Wgl.wglDeleteContext(RenderContext))
{
MessageBox.Show(_renderTarget, "No se pudo liberar al RenderContext",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
RenderContext = IntPtr.Zero;
//Liberamos al Device Context
if (!ReleaseDC(_renderTarget.Handle, DeviceContext))
{
MessageBox.Show(_renderTarget, "No se pudo liberar al Device Context",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
DeviceContext = IntPtr.Zero;
//y limpio la referencia a la ventana
_renderTarget = null;
return true;
}
#endregion
#region Metodos Privados
private Gdi.PIXELFORMATDESCRIPTOR llenarPixelFormatDescriptor()
{
Gdi.PIXELFORMATDESCRIPTOR pixelFormat = new Gdi.PIXELFORMATDESCRIPTOR();
pixelFormat.nSize = (short)Marshal.SizeOf(pixelFormat);
pixelFormat.nVersion = 1; //En Windows siempre es 1
pixelFormat.dwFlags = Gdi.PFD_DRAW_TO_WINDOW | Gdi.PFD_DOUBLEBUFFER |
Gdi.PFD_SUPPORT_OPENGL;
//La otra opcion en pixel Type es el modo paleta que es muy antiguo
pixelFormat.iPixelType = Gdi.PFD_TYPE_RGBA;
pixelFormat.cColorBits = ColorBits;
pixelFormat.cDepthBits = DepthBits;
pixelFormat.cStencilBits = 0; //No lo necesitamos en esta oportunidad
pixelFormat.cAuxBuffers = 0; //No es permitido en esta implementacion
pixelFormat.bReserved = 0; //No necesitamos underlay o overlay planes
pixelFormat.dwVisibleMask = 0; //No usamos Underlay planes
#region Propiedades que no usamos
pixelFormat.iLayerType = 0;
pixelFormat.dwLayerMask = 0;
pixelFormat.dwDamageMask = 0;
pixelFormat.cRedBits = 0;
pixelFormat.cGreenBits = 0;
pixelFormat.cBlueBits = 0;
pixelFormat.cAlphaBits = 0;
pixelFormat.cAccumBits = 0;
pixelFormat.cAccumBlueBits = 0;
pixelFormat.cAccumGreenBits = 0;
pixelFormat.cAccumRedBits = 0;
pixelFormat.cAccumAlphaBits = 0;
pixelFormat.cRedShift = 0;
pixelFormat.cGreenShift = 0;
pixelFormat.cBlueShift = 0;
pixelFormat.cAlphaShift = 0;
#endregion
return pixelFormat;
}
#endregion
}