Transparent Bug when additive blending and FOG enabled

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
peterparker
Posts: 11
Joined: Mon Nov 28, 2005 5:00 am
Location: N.Y.

Transparent Bug when additive blending and FOG enabled

Post 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
Xaron
Posts: 310
Joined: Sun Oct 16, 2005 7:39 am
Location: Germany
Contact:

Post 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
Panther
Posts: 34
Joined: Tue Jun 06, 2006 1:05 am

Fog bug still in irrlicht 1.3

Post 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!
Panther
Posts: 34
Joined: Tue Jun 06, 2006 1:05 am

Code correction for transparency

Post 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.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post 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
Post Reply