Page 1 of 1

Transparent Bug when additive blending and FOG enabled

Posted: Thu Dec 15, 2005 8:06 am
by peterparker
I recently found a bug when you enable additive blending and Fog with another color than black.
The additive blending of the fogged texture will result in a "doubled" colorvalue. For better understanding I made some snapshots:

bigger screenshotImage

Pic 1: This is my testapp: notice the billboard which is flying above the terrain.. nothing special to discover.. but ..

bigger screenshotImage

..if the billboard moves into the fog, there are nasty artefacts appearing..

I made a picture from a distance to show the bug very clear:

bigger screenshotImage

Explanation:
When drawing a fogged additive blended material, the color values will be blend into the fogcolor and then added to the screen. If fogcolor is not black,this procedure will result into a doubled fog color value as the fog color will be on screen and on the polygon and then added together.
Solution
Additive blending materials have to set the fogcolor to black and after render themselve they need to reset to current fog color.
This has to be done in CXXXDriver.cpp for each Videodriver. I would fix it, but unfortunately I cannot test implement DirectXrenderers.
So I hope a fix will make it into a next release.
Thanx in advance. And keep up the good work!
Peter

Posted: Wed Apr 05, 2006 8:35 am
by Xaron
Hi,

I've made a quick fix but in the SceneManager not in the VideoDriver:

Please add/change the following lines:

CNullDriver.h

AFTER:

Code: Select all

virtual void setFog(SColor color=SColor(0,255,255,255), bool linearFog=true,
  f32 start=50.0f, f32 end=100.0f, 
  f32 density=0.01f, bool pixelFog=false, bool rangeFog=false);
ADD:

Code: Select all

virtual void getFog(SColor& color, bool& linearFog, f32& start, f32& end, 
  f32& density, bool& pixelFog, bool& rangeFog);
CNullDriver.cpp

AFTER:

Code: Select all

//! Sets the fog mode.
void CNullDriver::setFog(SColor color, bool linearFog, f32 start, f32 end, f32 density,
  bool pixelFog, bool rangeFog)
{
  FogColor = color;
  LinearFog = linearFog;
  FogStart = start;
  FogEnd = end;
  FogDensity = density;
  PixelFog = pixelFog;
  RangeFog = rangeFog;
}
ADD:

Code: Select all

//! Gets the current fog settings
void CNullDriver::getFog(SColor& color, bool& linearFog, f32& start, f32& end, 
  f32& density, bool& pixelFog, bool& rangeFog)
{
  color = FogColor;
  linearFog = LinearFog;
  start = FogStart;
  end = FogEnd;
  density = FogDensity;
  pixelFog = PixelFog;
  rangeFog = RangeFog;
}
IVideoDriver.h

AFTER:

Code: Select all

virtual void setFog(SColor color=SColor(0,255,255,255), bool linearFog=true, f32 start=50.0f, f32 end=100.0f, 
  f32 density=0.01f, bool pixelFog=false, bool rangeFog=false) = 0;
ADD:

Code: Select all

virtual void getFog(SColor& color, bool& linearFog, f32& start, f32& end, 
  f32& density, bool& pixelFog, bool& rangeFog) = 0;
CSceneManager.cpp

in CSceneManager::drawAll()

REPLACE:

Code: Select all

// render transparent objects.

CurrentRendertime = ESNRP_TRANSPARENT;

TransparentNodeList.sort(); // sort by distance from camera

for (i=0; i<TransparentNodeList.size(); ++i)
  TransparentNodeList[i].node->render();

TransparentNodeList.clear();
WITH:

Code: Select all

// render transparent objects.

CurrentRendertime = ESNRP_TRANSPARENT;

TransparentNodeList.sort(); // sort by distance from camera

// save the current fog settings
video::SColor fogColor;
bool linearFog, pixelFog, rangeFog;
f32 fogStart, fogEnd, fogDensity;
Driver->getFog(fogColor, linearFog, fogStart, fogEnd, fogDensity, pixelFog, rangeFog);

for (i=0; i<TransparentNodeList.size(); ++i)
{
  video::SMaterial mat = TransparentNodeList[i].node->getMaterial(0);
  // set the fog color to black to get transparent things work correctly
  if (mat.MaterialType == video::EMT_TRANSPARENT_ADD_COLOR)
    Driver->setFog(video::SColor(0,0,0,0), linearFog, fogStart, fogEnd, fogDensity, pixelFog, rangeFog);
  else
    Driver->setFog(fogColor, linearFog, fogStart, fogEnd, fogDensity, pixelFog, rangeFog);
  TransparentNodeList[i].node->render();
}

// set the fog color back to the original one
Driver->setFog(fogColor, linearFog, fogStart, fogEnd, fogDensity, pixelFog, rangeFog);

TransparentNodeList.clear();
Regards - Xaron

Fog bug still in irrlicht 1.3

Posted: Mon May 07, 2007 9:31 pm
by Panther
It looks like peterparker's right (BTW, that's a cool nick, especially this weekend!).

Here's a pic with fog off (looks normal):

Image
http://panther.110mb.com/misc/compass_no_fog.jpg

When I am using Irrlicht v1.3 with fog on, you can see it's not transparent anymore (looks like frosted glass):

Image
http://panther.110mb.com/misc/compass_fog.jpg

I have not yet made the changes that Xaron suggested. It would be really great if this fix could go into Irrlicht v1.4!

Code correction for transparency

Posted: Tue May 08, 2007 1:03 am
by Panther
Be careful when you copy Xaron's CSceneManager.cpp code above. After the "//Render transparent objects" line, there is a Begin "{" and after the code there is an End "}".

I rebuilt Irrlicht, and Xaron's patch does fix the transparency problem! :D

However, I am getting a repetitive message:
Error: parallax map renderer only supports vertices of type EVT_TANGENTS
Not sure what is causing this! The error message is from the file CD3D9ParallaxMapRenderer.cpp.

Posted: Tue May 08, 2007 3:01 am
by vitek
You have a material that is using one of the EMT_PARALLAX_MAP_* material types, but the vertices used for that mesh are not of the correct type.

Travis