[fixed]Texture bug in OpenGL [GL_CLAMP]

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
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

[fixed]Texture bug in OpenGL [GL_CLAMP]

Post by ikam »

yopyop

There is a bug with texture wrapping in opengl. I tried to search in source but didn't found exactly where is it.

For my case texture borders are not correctly clamped on multi-terrain with flag ETC_CLAMP :

Image
Image

I found another thread with exactly the same problem : http://irrlicht.sourceforge.net/phpBB2/ ... e6f42ca9a5

Sometime borderlines are not visible but when approach very nearly it appear and never disapear when go away...

I tried to change code in COpenglDriver.cpp to always set data mode with GL_CLAMP for glTexparameteri functions at the end of setBasicRenderStates method :

Line borders disapears, but sometimes not. But when the camera move nearly borders, it disapear forever (inverse off before). very strange. I think the problem is quiet complex or depend of other things like mipmapping or other stuff like that.

This bug cause sometimes an access memory error in COpenGLDriver::setTransform(...)
at second line under case ETS_TEXTURE_3

All works fine in DirectX.

ps : for case of test you can use my terrain pager code and switch video driver to OpenGL
Last edited by ikam on Mon Jul 28, 2008 2:47 pm, edited 1 time in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Hmm, I checked the CLAMP code once more, and found no obvious problems (besides a difficult fallback and an inefficient check), but the basic functionality should be ok.
Which texture sizes do you use, how large's the heightmap? And did you alter the maximal texture units Irrlicht uses?
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Post by ikam »

- Textures size are 256x256
- Heightmap are 257x257
- I didn't change texture max unit

I'm going to try with others texture and hieghtmap size.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Heihgtmaps with 257x257 lead to buffer overflow, hence borders are usually corrupted.
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Post by ikam »

I'm using a custom scene node for rendering terrain, terrain is divided in multiple meshbuffers and uv coordinate divided per buffer and mapped from 0 to 1 over the sum of mini buffers. But problem is not here. I tested this simple code with 2 cube node and ETC_CLAMP :

Code: Select all

#include <irrlicht.h>
#pragma comment(lib, "Irrlicht.lib")
using namespace irr;

int main(int argc, char **argv)
{
	// irrlicht parametres
	irr::SIrrlichtCreationParameters param;
	param.DriverType = video::EDT_OPENGL;
	param.WindowSize = core::dimension2di(800,600);
	IrrlichtDevice * device = createDeviceEx(param);

    // get irr pointers
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager * smgr = device->getSceneManager();
    gui::IGUIEnvironment * guienv = device->getGUIEnvironment(); 

	// add camera fps
	scene::ICameraSceneNode * cam =  smgr->addCameraSceneNodeFPS(0,100,100.0f);
	cam->setPosition(core::vector3df(5,0,-16));
	device->getCursorControl()->setVisible(false);
	
	scene::ISceneNode * n1 = smgr->addCubeSceneNode(10);
	n1->setPosition(core::vector3df(0,0,0));
	n1->setMaterialTexture(0, smgr->getVideoDriver()->getTexture("Media2/map13.png"));
	n1->getMaterial(0).TextureLayer[0].TextureWrap = video::ETC_CLAMP;	
	n1->setMaterialFlag(video::EMF_LIGHTING, false);
	
	scene::ISceneNode * n2 = smgr->addCubeSceneNode(10);
	n2->setPosition(core::vector3df(10,0,0));
	n2->setMaterialTexture(0, smgr->getVideoDriver()->getTexture("Media2/map14.png"));
	n2->getMaterial(0).TextureLayer[0].TextureWrap = video::ETC_CLAMP;
	n2->setMaterialFlag(video::EMF_LIGHTING, false);


    while(device->run())
    {
		driver->beginScene(true, true, video::SColor(255,80,80,80));             
			smgr->drawAll();			
            guienv->drawAll();
         driver->endScene();   		
	}

    device->drop();
    return 0;
} 
result in opengl :

Image

No problem in directx


media used :

Image Image
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Post by ikam »

bug disapear when I comment the line in COpenglDriver.cpp in setBasicRenderStates :

Code: Select all

if (resetAllRenderStates || lastMaterial.TextureLayer[u].TextureWrap != material.TextureLayer[u].TextureWrap) 
In texture adresse mode section.

So I search something wrong in setRenderStates3DMode with maybe a bad init of lastMaterial... Code is not exactly the same than in CD3D9Driver.cpp but after replace with the same code used in d3d9 the result doesn't change.

Is there a really interrest to perform previous test in setBasicRenderStates ?

When debugging setBasicRenderStates i saw texture adresse mode set to GL_REPEAT as default, with a breakpoint here I saw mode changing to GL_CLAMP as I want for my textures but frequently re-change to GL_REPEAT in a new material even if I never use any other texure with a different wrapping mode. normal ?

bug still here, to be continued...
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Ok, thanks for the debuggin. I think I know now why this fails. It's due to clamp changes in the 2d modes, which are not recognised by the material states of the opengl driver. So it thinks the clamp mode is still valid, although it was changed. I'll fix it soon (Once I figured a proper and cheap way...)
Edit: The SVN should already work as it is now. However, we might do even better and avoid the continuous reset of the texture filter flags with the new 2d init scheme. Maybe you could try against latest SVN trunk to check if the bug was solved?
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Post by ikam »

tested quickly but still doesn't work with last svn version. I 'll try to debug with new code tomorow.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, you were right with your first suggestion. Since wrap modes are per texture we'd have to check for the correct texture as well. I've changed the setup to ignore this and always set the texture wrap mode, just as the texture filtering is initialized. So revision 1424 should work now.
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Post by ikam »

result is different between opengl and d3d9 in setBasicRenderStates function on texture address mode part :

for debug I added a function at loop start to get GL_TEXTURE_WRAP_S(opengl) or D3DSAMP_ADDRESSU(d3d9) state

Code: Select all

opengl => glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, debug_state);
d3d9 => pID3DDevice->GetSamplerState(st, D3DSAMP_ADDRESSU, debug_state);

in conclusion :

In d3d9 wrap mode is ETC_CLAMP for every material.TextureLayer[0] (every material solid texture) and ETC_REPEAT for material.TextureLayer[1,2 and 3] (normal no defined texture here).

In opengl wrap mode is ETC_CLAMP for TextureLayer[0,1,2 and 3] on first material and switch to ETC_REPEAT for TextureLayer[0,1,2 and 3] for every others materials, only the first material have ETC_CLAMP but its 4 texturelayers also have ETC_CLAMP (only texturelayer[0] would be ETC_CLAMP).

OpenGL seem to keep wrap state after to set up it for a material texture layer. But need to be setup again for other material. Code is not correct beacause there is a difference state between material.TextureLayer.TextureWrap and active opengl wrap mode

I think opengl should work differently as d3d9 and maybe set up wrap mode for every texturelayer on every material with a test on the last opengl wrap state returned by glGetTexParameteriv and the actual material.TextureLayer.TextureWrap to setup correct wrap mode if different.


EDIT : I didn't saw but :

D3D9 use SetSamplerState(st, D3DSAMP_ADDRESSU, mode); with st as index for texturelayer. (so only one texturelayer is affected on wanted material)

And opengl use glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode); without specify texturelayer but last texture binded (so all texturelayer of actual material are affected).

This explain previously differences :p
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Where did you test the values, and did you properly choose the texture layers for reading back the actual values?
I couldn't find any problems with the init ATM, all mode changes are made after the texture was set, so all filter and clamp modes are applied to the correct texture.
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Post by ikam »

Yes you right, changes are made after texture was set and applied to correct texture, but real opengl wrap mode is reset between rendering objects. So in next rendering object materials.TextureWrap and lastMaterials.TextureWrap are equals if they are both ETC_CLAMP but not for opengl because code doesn't see difference between materials and lastmaterials so doesn't setup GL_CLAMP for second texture...

(i don't know if it is understandable) (ohh my poor english)... so let's see in details when debuggin :

I tested this values after init when rendering cubes (previously posted code)

when rendering each cube, setBasicRenderStates is called each time.

I set breakpoint on setBasicRenderStates on "set texture mode" section.

---------------------------------------------------------------------------------------

first break (first cube)

First iterarion : (first texturelayer)

- glGetTexParameteriv return value is GL_REPEAT (default) (ok)
- material.TextureLayer[0] exist (valid adress) (first texture).
- lastmaterial = ETC_REPEAT and material = ETC_CLAMP (as wanted) (ok)
- material mode are different so enter if block and call glTexParameteri with GL_CLAMP and actual opengl binded texture parameters. (good job)

second iteration : (second texturelayer)

- glGetTexParameteriv return value is GL_CLAMP (set previously) (wrong, would be reset to GL_REPEAT as default)
- material.TextureLayer[1] doesn't exist (so wrap mode is default value => ETC_REPEAT)
- lastmaterial = ETC_REPEAT and material = ETC_REPEAT (default value) (logic)
- no difference, no change

same with third and fourth iteration


---------------------------------------------------------------------------------------

second break (second cube)

fisrt iteration :

- glGetTexParameteriv return value is GL_REPEAT (reset ? where ? maybe by opengl functions like gldisable... after rendiering object, don't know exactly)
- material.TextureLayer[0] exist (valid adress) (second texture).
- lastmaterial = ETC_CLAMP and material = ETC_CLAMP (normal)
- material mode are equal so no change. But real opengl wrap mode was reset to GL_REPEAT so second texture binded is not correctly wrapped with GL_CLAMP.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Maybe you're using the wrong SVN branch or revision, but there's no condition for the texture wrap modes now. So the wrap modes are set in each layer in each call to setBasicRenderStates. The only problems that I still see are wrong modes used in 3d render methods with textures. Since I don't reset the filter and clamp modes anymore, the modes might become wrongly set.
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Post by ikam »

Yes, you were right i didn't debug with latest version :lol:

I didn't test yet but should be ok like this, i'll confirm later. Thanks for support.
Sinsemilla
Posts: 38
Joined: Mon Jan 09, 2012 5:07 pm

Re: [fixed]Texture bug in OpenGL [GL_CLAMP]

Post by Sinsemilla »

Hi,

I am sorry to bump such an old thread, but i this old problem reappears to me when i try to use the code from here: http://irrlicht.sourceforge.net/forum/v ... rain+pager. To give a little more explanation: After i decided to reuse this code which was lying around on my computer for almost 2 years, the problem reemerged suddenly.

I am not sure if this is a regression in Irrlicht or related to something else like perhaps the actual graphics driver which i suspect to cause this, since i tested this issue from irrlicht 1.8 down to the irrlicht 1.7 release version and the bug was always occuring. The only change in my computer since then was the nvidia graphics driver. My hardware is an Nvidia GTX-460, the driver version 304.88.

This is happening under OpenGL in Linux, i didnt test the DirectX part.
Post Reply