OpenGLsetTexture Material bug and cause

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
mpenacho
Posts: 3
Joined: Wed Apr 29, 2009 8:03 pm

OpenGLsetTexture Material bug and cause

Post by mpenacho »

I'm using Irrlicht on Linux/OpenGL and found a problem in the Irrlicht LastMaterial caching optimization.

If I have a scene that renders the following textures in the following order

AABCCBA

It will remember the settings of the current material and of the current openGL texture stages. This will cause a new texture to be set only when the material and texture changes.

(uppercase = opengl texture stage set, lowecase = opengl texture stage not set (still the same)

AaBCcBA - and for subsequent frames
aaBCcBA
aaBCcBA - (the first frame's texture stage is not set because the previous frame ended with the same texture)

The problem is, if in between frames, addTexture(..) is called, this will upset the OpenGL texture stage, but Irrlicht is not aware of this change, and the following will occur

AaBCcBA
aaBCcBA
aaBCcBA addTexture(..) is now called, creating texture D
ddBCcBA - D is drawn instead of A, because Irrlicht thinks A is still current
aaBCcBA - corrects itself for the next frame
aaBCcBA

There are two stages in the code that prevent the new texture stage from being set.

first - LastMaterial is still equal to Material, and all the inequality tests in several places in the code are showing equality, and any relevant settings are being skipped

second - in bool COpenGLDriver::setTexture(u32 stage, const video::ITexture* texture), near the top of the function, there is this additional test

if (CurrentTexture[stage]==texture)
return true;

that is also preventing the texture stage from being correctly reset

This can be fixed by adding the following changes to bool COpenGLDriver::beginScene(...), after the CNullDriver::beginScene()

// reset the OpenGL texture stages
disableTextures(0);
// force the current 'LastMaterial' to not match
// EMT_FORCE_32BIT is guaranteed to force an inequality for next test
LastMaterial.MaterialType = EMT_FORCE_32BIT;
Post Reply