PDA

View Full Version : OpenGL: Silly texturing problem



vgo
06-04-2006, 06:05 PM
After a few years (maybe 5 or 6) I decided to pick up again on OpenGL programming and I ran into a strange problem.

I load 6 textures using the glBitmap.LoadTexture function and I try to render a cube with different texture on each side.

I enable texturing, bind the right texture, set normals, texture coordinates and vertices and I get the last texture I loaded on each side.

What could be wrong? I've done this million times and I even digged up some old code that works and I'm doing exactly the same as in there... :oops:

Traveler
06-04-2006, 06:13 PM
Are you sure you are using glBindTexture for all sides seperately?

In any case, some sample code would help..

vgo
06-04-2006, 07:09 PM
Here's the code:

procedure TSkyBox.Render;
var
i, j: Integer;
begin
glEnable(GL_TEXTURE_2D);
glColor3f(1, 1, 1);
glBegin(GL_QUADS);
for i := 0 to 5 do
begin
glBindTexture(GL_TEXTURE_2D, TexID[i]);
glNormal3fv(@Normals[i]);
for j := 0 to 3 do
begin
glTexCoord2fv(@TexCoord[j]);
glVertex3fv(@Vertices[Quads[i, j]]);
end;
end;
glEnd; // GL_QUADS
glDisable(GL_TEXTURE_2D);
end;


I had the texture ids written to a log file and they were 1-6, just like they should be with them being the only textures generated so far.
For some reason the binding doesn't work.

vgo
06-04-2006, 08:15 PM
Figured it out, I have to bind the texture outside glBegin() - glEnd() blocks.


procedure TSkyBox.Render;
var
i, j: Integer;
begin
glColor3f(1, 1, 1);
glEnable(GL_TEXTURE_2D);
for i := 0 to 5 do
begin
glBindTexture(GL_TEXTURE_2D, TexID[i]);
glBegin(GL_QUADS);
glNormal3fv(@Normals[i]);
for j := 0 to 3 do
begin
glTexCoord2fv(@TexCoord[j]);
glVertex3fv(@Vertices[Quads[i, j]]);
end;
glEnd; // GL_QUADS
end;
glDisable(GL_TEXTURE_2D);
end;


Guess I have to refresh my memory a bit before moving on to the good stuff... :)

michalis
06-04-2006, 08:52 PM
Hint: You should check glGetError from time to time (e.g. after rendering every frame). This will automatically catch errors like this one, using some disallowed function between glBegin and glEnd.

vgo
07-04-2006, 06:40 AM
Yeah, I've already added the check to the main loop. I just couldn't think that I'd run into problems in something as trivial as this. :)

vgo
08-04-2006, 07:36 AM
Looks like that wasn't the end of the problems...

For some reason I get $0502 (invalid operation) everytime I call glEnd()...

Even something as simple as this won't work:

glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 0.0);
glVertex3f( 1.0, 1.0,-1.0);
glVertex3f(-1.0, 1.0,-1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f( 1.0, 1.0, 1.0);
glEnd();

michalis
08-04-2006, 04:46 PM
Even something as simple as this won't work:
...


This looks like a good code, OpenGL shouldn't complain about this. So the error must be somewhere else. Can you show complete code that doesn't work ?

Also you can always check glGetError more often, this should give you more precise hints which operation is invalid. (But remember that glGetError is not allowed between glBegin...glEnd, so you can't put it there).

Clootie
08-04-2006, 11:16 PM
Try GLexpert

vgo
09-04-2006, 09:32 AM
Here's the simplified rendering code that still produces the error.

procedure glCheckForError;
var
glError: TGLenum;
begin
glError := glGetError();
if (glError <> GL_NO_ERROR) then
raise EOpenGLError.Create('OpenGL error! Code: ' +
IntToStr(glError) + ' ($' + IntToHex(glError, 4) + ' hex) Description: ' +
gluErrorString(glError));
end;

procedure Init;
begin
glClearColor(0.0, 0.0, 0.0, 0.0);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_MODELVIEW);
end;

procedure Render;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glRotatef(-FCamera.Pitch, 1, 0, 0);
glRotatef(-FCamera.Yaw, 0, 1, 0);
glTranslatef(-FCamera.Pos.x, -FCamera.Pos.y, -FCamera.Pos.z);
glCheckForError(); // Everything is ok here

glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 0.0);
glVertex3f( 1.0, 1.0,-1.0);
glVertex3f(-1.0, 1.0,-1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f( 1.0, 1.0, 1.0);
glEnd();
glCheckForError(); // $0502 GL_INVALID_OPERATION here
end;


Rendering actually works and everything is rendered correctly, but I just always get the error from each glEnd() call. Doesn't matter what primitives I try to draw, quads, triangles, lines, points, it's all the same...

I'm using the latest version of dglOpenGL and I use a custom panel component for rendering. I have Radeon 9800Pro with latest drivers, running on WinXP corporate edition with all latest patches. I'm using Borland Developer Studio 2006 Architect to write the code.


Try GLexpert

What's that?

cragwolf
09-04-2006, 10:42 AM
This is just a stab in the dark, and will probably have no effect whatsoever, but why not try removing the () from the parameterless function calls, like glEnd, glGetError, etc.

vgo
09-04-2006, 11:09 AM
Nope, that's not it. Parentheses or not, still the same error...

michalis
09-04-2006, 04:26 PM
Here's the simplified rendering code that still produces the error.
...

Hmm. That's really strange. Your code is perfectly fine, shouldn't cause any OpenGL errors. I even created a simple program, copy&pasted your code into Init and Draw, and (after changing FCamera references to compile) everything runs OK. No OpenGL error.

(Note that I used FPC 2.0.2 on Linux with NVidia card, so my environment was quite different than yours. But your sample OpenGL code should work the same.)

Moreover, you say that rendering works good. Which is another proof that things between glBegin...glEnd are correct. If something would be incorrect between glBegin...glEnd, rendering results would be incorrect also.

So, basically, your code is good. The error must be somewhere else. Inside dglOpenGL bindings ? Something specific to Borland Arch 2006 ? Something specific to Radeon ? All these causes are very very very unlikely.

Are you sure that you don't have another thread running in your program that does some OpenGL calls ?

Otherwise, I'm afraid you'll have to send/show somewhere the complete program code to reproduce the bug. I don't have Borland Arch 2006 or Radeon, but I can try to test with Delphi 7 on NVidia. Maybe someone else will have Borland Arch 2006 and Radeon. This will allow us to test exactly your program, and maybe this way we'll discover something.

vgo
10-04-2006, 02:51 PM
I tried to duplicate the error with a simple pure Windows API program, can't do it. Everything works like a charm...

Maybe it has something to do with the custom OpenGL panel that I'm using?

Here's code for the OpenGL panel component:

unit glWindow;

interface

uses
Windows, Classes, Graphics, Forms, dglOpenGL, extctrls;

type
// Types for OpenGL window settings
TWindowOption = (wfDrawToWindow, wfDrawToBitmap, wfSupportGDI,
wfSupportOpenGL, wfGenericAccelerated, wfDoubleBuffer);
TWindowOptions = set of TWindowOption;

TDepthBits = (c16bits, c32bits);

TResizeEvent = procedure(Sender : TObject) of object;
TDrawEvent = procedure(Sender : TObject) of object;
TInitEvent = procedure(Sender : TObject) of object;

TglWindow = class(TCustomPanel)
private
h_RC : HGLRC; // Rendering context
Init : Boolean; // Whether panel has been initalized yet
FColorDepth : Integer; // Color depth
FDepthBits : Integer; // Depth buffer depth
FDepthEnabled : Boolean; // Enables the depth buffer
FStencBits : Integer; // Stencil buffer depth
FStencEnabled : Boolean; // Enables the stencil buffer
FAccumBits : Integer; // Accumulation buffer depth
FAccumBufferEnabled : Boolean; // Enables the accumulation buffer
FWindowFlags : TWindowOptions; // OpenGL window properties
FOnResize : TResizeEvent; // OpenGL resize function
FOnDraw : TDrawEvent; // OpenGL draw function
FOnInit : TInitEvent; // OpenGL initialization function
OldClose : TNotifyEvent; // Saves old close event from form
flags : Word; // OpenGL window flags
rot : Integer; // rotation amount for cube in default
// drawing code

procedure Close(Sender: TObject);
function GetColorDepth() : TDepthBits;
procedure SetColorDepth(depth : TDepthBits);
function GetDepthBufferDepth() : TDepthBits;
procedure SetDepthBufferDepth(depth : TDepthBits);
function GetStencBufferDepth() : TDepthBits;
procedure SetStencBufferDepth(depth : TDepthBits);
function GetAccumBufferDepth() : TDepthBits;
procedure SetAccumBufferDepth(depth : TDepthBits);
procedure defResize(Sender : TOBject);
procedure defDraw(Sender : TObject);
procedure defInit(Sender : TObject);
procedure SetWindowFlags();
public
h_DC : HDC; // Device context
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Loaded; override;
procedure Paint; override;
procedure ReDraw();
procedure Swap; // Swaps the buffer's if display is double buffered
procedure Resize; override;
published
property Align;
property Visible;
property OnClick;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnDblClick;
property ColorDepth : TDepthBits read GetColorDepth write SetColorDepth;
property DepthBits : TDepthBits read GetDepthBufferDepth write SetDepthBufferDepth;
property DepthBufferEnabled : Boolean read FDepthEnabled write FDepthEnabled;
property StencBits : TDepthBits read GetStencBufferDepth write SetStencBufferDepth;
property StencBufferEnabled : Boolean read FStencEnabled write FStencEnabled;
property AccumBits : TDepthBits read GetAccumBufferDepth write SetAccumBufferDepth;
property AccumBufferEnabled : Boolean read FAccumBufferEnabled write FAccumBufferEnabled;
property WindowFlags : TWindowOptions read FWindowFlags write FWindowFlags;
property OnResize : TResizeEvent read FOnResize write FOnResize;
property OnDraw : TDrawEvent read FOnDraw write FOnDraw;
property OnInit : TInitEvent read FOnInit write FOnInit;
end;

procedure Register;

implementation

procedure Register;
begin
// Register glWindow component so its displayed in the Tool Palette
RegisterComponents('OpenGL', [TGLWindow]);
end;

{ TGLWindow }

// Name : Create
// Purpose : Creates the glWindow component
// Parameters : Owner of the component
constructor TGLWindow.Create(AOwner: TComponent);
var
frm : TForm;
begin
inherited Create(AOwner);
InitOpenGL;
// Set background color and pen and brush colors
Color := clBlack;
Canvas.Brush.Color := clBlack;
Canvas.Pen.Color := clBlack;

if csDesigning in ComponentState then begin
// Set default width and height
Width := 65;
Height := 65;

// Set up initial rendering settings
{$IFDEF FPC}
{$ELSE}
FDoubleBuffered := True;
{$ENDIF}
FColorDepth := 16;
FDepthBits := 16;
FDepthEnabled := True;
FStencBits := 16;
FStencEnabled := False;
FAccumBits := 16;
FAccumBufferEnabled := False;
FWindowFlags := [wfDrawToWindow, wfSupportOpenGL, wfDoubleBuffer];
end else begin

// component hasn't been initialized yet (no rendering context, etc...)
Init := False;

// Get a handle on the form that the component is on
frm := TForm(AOwner);

// Set this component to be destroyed when the form is destroyed
if Assigned(frm.OnDestroy) then
OldClose := frm.OnDestroy;
{$IFDEF FPC}
frm.OnDestroy := @Close;
{$ELSE}
frm.OnDestroy := Close;
{$ENDIF}


// Set default OpenGL routines, if no draw/resize/or init routines are
// specified then the default ones are used, the default drawing routine
// simply draws a rotating cube
{$IFDEF FPC}
OnResize := @defResize;
OnDraw := @defDraw;
OnInit := @defInit;
{$ELSE}
OnResize := defResize;
OnDraw := defDraw;
OnInit := defInit;
{$ENDIF}

end;
end;

// Name : defInit
// Purpose : default OpenGL initialization
procedure TGLWindow.defInit(Sender: TObject);
begin
glClearColor(0.0, 0.0, 0.0, 0.0);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
end;

// Name : defResize
// Purpose : Default resize routine
procedure TGLWindow.defResize(Sender: TOBject);
var
fAspect : GLfloat;
begin
// Make sure that we don't get a divide by zero exception
if (Height = 0) then
Height := 1;

// Set the viewport for the OpenGL window
glViewport(0, 0, Width, Height);

// Calculate the aspect ratio of the window
fAspect := (Width / Height);

// Go to the projection matrix, this gets modified by the perspective
// calulations
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Do the perspective calculations
gluPerspective(45.0, fAspect, 1.0, 1000.0);

// Return to the modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
end;

// Name : defDraw
// Purpose : Default drawing routine, draws spinning cube
procedure TGLWindow.defDraw(Sender: TObject);
begin
// Clear the color and depth buffers
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

// Replaces the current matrix with the identity matrix
glLoadIdentity();

// Go to the model view matrix mode
glMatrixMode(GL_MODELVIEW);

// Sample drawing code, draw's a rotating cube onscreen
glTranslatef(0.0, 0.0, -5.0);
glRotatef(rot, 1.0, 1.0, 0.0); // Rotates around the x and y axis

glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 0.0);
glVertex3f( 1.0, 1.0,-1.0);
glVertex3f(-1.0, 1.0,-1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f( 1.0, 1.0, 1.0);

glColor3f(1.0, 0.5, 0.0);
glVertex3f( 1.0,-1.0, 1.0);
glVertex3f(-1.0,-1.0, 1.0);
glVertex3f(-1.0,-1.0,-1.0);
glVertex3f( 1.0,-1.0,-1.0);

glColor3f(1.0, 0.0, 0.0);
glVertex3f( 1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0,-1.0, 1.0);
glVertex3f( 1.0,-1.0, 1.0);

glColor3f(1.0, 1.0, 0.0);
glVertex3f( 1.0,-1.0,-1.0);
glVertex3f(-1.0,-1.0,-1.0);
glVertex3f(-1.0, 1.0,-1.0);
glVertex3f( 1.0, 1.0,-1.0);

glColor3f(0.0, 0.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0,-1.0);
glVertex3f(-1.0,-1.0,-1.0);
glVertex3f(-1.0,-1.0, 1.0);

glColor3f(1.0, 0.0, 1.0);
glVertex3f( 1.0, 1.0,-1.0);
glVertex3f( 1.0, 1.0, 1.0);
glVertex3f( 1.0,-1.0, 1.0);
glVertex3f( 1.0,-1.0,-1.0);
glEnd();

Inc(rot); // Increment the current cube rotation amount
end;

destructor TGLWindow.Destroy;
begin
inherited Destroy;
end;

// Name : GetAccumBufferDepth
// Purpose : Gets the current accumulation buffer depth
// Returns : Current accumulation buffer depth
function TGLWindow.GetAccumBufferDepth() : TDepthBits;
begin
case FAccumBits of
16 : Result := c16bits;
32 : Result := c32bits;
else Result := c16bits;
end;
end;

// Name : GetColorDepth
// Purpose : Gets the current OpenGL color depth
// Returns : Current OpenGL color depth
function TGLWindow.GetColorDepth() : TDepthBits;
begin
case FColorDepth of
16 : Result := c16bits;
32 : Result := c32bits;
else Result := c16bits;
end;
end;

// Name : GetDepthBufferDepth
// Purpose : Gets the current depth of the depth buffer
// Returns : The current depth of the depth buffer
function TGLWindow.GetDepthBufferDepth() : TDepthBits;
begin
case FDepthBits of
16 : Result := c16bits;
32 : Result := c32bits;
else Result := c16bits;
end;
end;

// Name : GetStencBufferDepth
// Purpose : Gets the stencil buffer depth
// Returns : Current stencil buffer depth
function TGLWindow.GetStencBufferDepth() : TDepthBits;
begin
case FStencBits of
16 : Result := c16bits;
32 : Result := c32bits;
else Result := c16bits;
end;
end;

// Name : Paint
// Purpose : Paints the OpenGL component black when its first put on the form
procedure TGLWindow.Paint;
begin
if csDesigning in ComponentState then
Canvas.Rectangle(0, 0, Width, Height)
else
ReDraw;
end;

// Name : SetAccumBufferDepth
// Purpose : Sets the accumulation buffer depth
// Parameters :
// depth - new depth for accumulation buffer
procedure TGLWindow.SetAccumBufferDepth(depth : TDepthBits);
begin
case depth of
c16bits : FAccumBits := 16;
c32bits : FAccumBits := 32;
end;
end;

// Name : SetColorDepth
// Purpose : Sets the window color depth
// Parameters :
// depth - new color depth for the window
procedure TGLWindow.SetColorDepth(depth : TDepthBits);
begin
case depth of
c16bits : FColorDepth := 16;
c32bits : FColorDepth := 32;
end;
end;

// Name : SetDepthBufferDepth
// Purpose : Sets the depth of the depth buffer
// Parameters :
// depth - new depth for the depth buffer
procedure TGLWindow.SetDepthBufferDepth(depth : TDepthBits);
begin
case depth of
c16bits : FDepthBits := 16;
c32bits : FDepthBits := 32;
end;
end;

// Name : SetStencBufferDepth
// Purpose : Sets the stencil buffer depth
// Parameters :
// depth - New depth for the stencil buffer
procedure TGLWindow.SetStencBufferDepth(depth : TDepthBits);
begin
case depth of
c16bits : FStencBits := 16;
c32bits : FStencBits := 32;
end;
end;

// Name : Resize
// Purpose : Called when the width or height of the component changes, in
// turn it calls the resize procedure assigned to the component
procedure TGLWindow.Resize;
begin
// Make this components rendering context current
wglMakeCurrent(h_DC, h_RC);

// Call assigned resize event if component has been initialized
if (Assigned(OnResize) and (Init))
then OnResize(self);
end;

// Name : ReDraw
// Purpose : Called when owner want's opengl window to be updated, in turn
// it calls the draw function assigned to the component
procedure TGLWindow.ReDraw;
begin
// Make this components rendering context current
wglMakeCurrent(h_DC, h_RC);

// Call assigned drawing routine, updating the OpenGL scene
if Assigned(OnDraw) then OnDraw(self);

// Swap the buffers if needed
Swap;
end;

// Name : Swap
// Purpose : Swaps the OpenGL buffers if display is double buffered
procedure TGLWindow.Swap;
begin
if wfDoubleBuffer in FWindowFlags then SwapBuffers(h_DC);
end;

// Name : Loaded
// Purpose : Sets the pixel format and attaches a rendering context to the
// components device context
procedure TGLWindow.Loaded;
var
PixelFormat : Integer;
pfd : PIXELFORMATDESCRIPTOR;
begin
inherited;

// Update the window flags
SetWindowFlags();

// Set all fields in the pixelformatdescriptor to zero
ZeroMemory(@pfd, SizeOf(pfd));

// Initialize only the fields we need
pfd.nSize := SizeOf(PIXELFORMATDESCRIPTOR); // Size Of This Pixel Format Descriptor
pfd.nVersion := 1; // The version of this data structure
pfd.dwFlags := flags; // Set the window flags
// (set in property editor)
pfd.iPixelType := PFD_TYPE_RGBA; // Set OpenGL pixel data type
pfd.cColorBits := FColorDepth; // OpenGL color depth
pfd.cDepthBits := FDepthBits; // Specifies the depth of the depth buffer

// If component's settings specifies that the accumulation buffer is enabled
// then set its depth (which enables it)
if FAccumBufferEnabled then
pfd.cAccumBits := FAccumBits;

// If component's settings specifies that the stencil buffer is enabled
// then set its depth (which enables it)
if FStencEnabled then
pfd.cStencilBits := FStencBits;

h_DC := GetDC(Handle);

// Attempts to find the pixel format supported by a device context that is the
// best match to a given pixel format specification.
PixelFormat := ChoosePixelFormat(h_DC, @pfd);
if (PixelFormat = 0) then begin
Close(self);
MessageBox(0, 'Unable to find a suitable pixel format', 'Error', MB_OK or MB_ICONERROR);
Exit;
end;

// Sets the specified device context's pixel format to the format specified by
// the PixelFormat.
if (not SetPixelFormat(h_DC, PixelFormat, @pfd)) then begin
Close(self);
MessageBox(0, 'Unable to set the pixel format', 'Error', MB_OK or MB_ICONERROR);
Exit;
end;

// Create a OpenGL rendering context
h_RC := wglCreateContext(h_DC);
if (h_RC = 0) then begin
Close(self);
MessageBox(0, 'Unable to create an OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Exit;
end;

// Makes the specified OpenGL rendering context the calling thread's current
// rendering context
if (not wglMakeCurrent(h_DC, h_RC)) then begin
Close(self);
MessageBox(0, 'Unable to activate OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Exit;
end;

// Component has a rendering context
Init := True;

// Call assinged initialization routine and resize routine
if Assigned(OnInit) then OnInit(self);
if Assigned(OnResize) then OnResize(self);

// Updates the OpenGL scene
ReDraw;
end;

// Name : Close
// Purpose : Removes and deletes the components rendering context
procedure TglWindow.Close(Sender : TObject);
begin
// Makes current rendering context not current, and releases the device
// context that is used by the rendering context.
wglMakeCurrent(h_DC, 0);

// Attempts to delete the rendering context
wglDeleteContext(h_RC);

// Release the device context (return the memory)
ReleaseDC(Handle, h_DC);

Init := False;

// If old close event was saved, call it
if Assigned(OldClose) then OldClose(Sender);
end;


// Name : SetWindowFlags
// Purpose : Sets the OpenGL window flags depending on the values specified
// in the property editor for the component
procedure TglWindow.SetWindowFlags;
begin
if wfDrawToWindow in FWindowFlags then flags := flags or PFD_DRAW_TO_WINDOW;
if wfDrawToBitmap in FWindowFlags then flags := flags or PFD_DRAW_TO_BITMAP;
if wfSupportOpenGL in FWindowFlags then flags := flags or PFD_SUPPORT_OPENGL;
if wfGenericAccelerated in FWindowFlags then flags := flags or PFD_GENERIC_ACCELERATED;

// A window can't have both double buffering and gdi support in Microsoft's
// OpenGL implementation. So support double buffering if requested and only
// if it isn't do we support GDI operations
if wfDoubleBuffer in FWindowFlags then
flags := flags or PFD_DOUBLEBUFFER
else if wfSupportGDI in FWindowFlags then
flags := flags or PFD_SUPPORT_GDI;

end;

end.

vgo
10-04-2006, 06:30 PM
Ok, this gets more bizarre every day...

I made a simple test app with Lazarus and guess what? YES! The same ****ing error message!!! This is getting ridiculous... It's different from Delphi tho, NOTHING seem to get rendered...

I reinstalled the display drivers and left out the stupid Catalyst control center too, but it doesn't make any difference...

EDIT: Now it seems to work. Haven't got it to render anything yet, but at least there's no errors. :P

Clootie
10-04-2006, 08:54 PM
Try GLexpert
What's that?
It's developer tool made by NVIDIA for catching "wrong" usage of OpenGL API (something like debug layer of DirectX).
Presentation: NVIDIA developer tools on GDC-2006 (http://developer.nvidia.com/object/opengl-performance-tools-gdc-2006.html).

Hm... Seems it's still unavailable for download from NVIDIA site - it's only on these DVD's with SDK.

michalis
10-04-2006, 11:22 PM
Here's code for the OpenGL panel component:
...


OK, I was finally able to reproduce your problem.

1. I took glWindow unit your submitted
2. I downloaded dglOpenGL
3. I placed your glBegin(GL_QUADS); ... glEnd(); glCheckForError(); snippet in OnDraw

...and now I get GL_INVALID_OPERATION. This is with Delphi 7, on NVidia, Windows 2000 Prof.

The problem seems to be inside dglOpenGL unit related to the STUB_xxx tricks they are doing. When I avoid relaying on STUB_xxx tricks, things suddenly work OK.

Two solutions that work for me:
1. Call ReadOpenGLCore right after InitOpenGL inside TGLPanel.Create
2. Or use other Delphi header than dglOpenGL header. E.g. when using standard Delphi OpenGL unit with the same code, problem disappears.

vgo
11-04-2006, 02:12 PM
I tracked it down to dglOpenGL too, but didn't catch the specific reason.

I had the same problem on my Lazarus test program, but as soon as I started using the TOpenGLControl and the supplied GL/GLU units I got rid off that error.

Good thing is that this episode really forced me to look more into Lazarus and as a result of that my game engine is now cross-platform. :)
It's far from a full blown commercial game engine, but that's not the point, I'm doing this for the fun of it. :D

Which sort of brings up another OpenGL question... Are the display lists obsolete, is there any performance gain from using them? Back in the day they were very useful along with the vertex arrays, now there seems to be vertex buffer objects too...

technomage
11-04-2006, 03:20 PM
I don't think display lists are obsolete. They still give the driver the chance to cache and optimize data. Admittedly they are not a quick are vertex arrays or vertex buffers, but they are very flexable and easy to use.