Light Oversaturation

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
nullterm
Posts: 14
Joined: Tue Feb 27, 2007 12:36 pm

Light Oversaturation

Post by nullterm »

I'm trying to get a point light to illuminate my scene correctly. However, the light is oversaturated on the lit side. So that the vertices are either super bright, or not lit at all.

There spheres each have 512 triangles so there should be a smooth gradient. And you should see some color difference between the top and side faces of the boxes.

I manually inspected the .obj normals and the look like they have a unit length (1.0).

If I lower the radius (10000.0f -> 400.0f), then it appears to improve the smoothness of the lighting. But why is the radius affecting the light intensity?

If I reduce the radius, then the light won't affect all the objects in my final scene. So I need a high Radius, but don't want it affecting the brightness of the scene.

If I switch to a directional light, then it appears I lose the shadows (which are the main reason I'm investigating Irrlicht as a rendering solution).

Image

Source:

Image
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

are your normals normalized? if they have a length of anything other than 1.0 then you'll have lighting problems.
you can either recalculate them with the mesh manipulator, or if you want to keep their direction you can set the normalize normals SMaterial flag and let the hardware fix them.
If that's not the problem, perhaps you can post the contents of the MTL file here
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
nullterm
Posts: 14
Joined: Tue Feb 27, 2007 12:36 pm

Post by nullterm »

bitplane wrote:are your normals normalized? if they have a length of anything other than 1.0 then you'll have lighting problems.
you can either recalculate them with the mesh manipulator, or if you want to keep their direction you can set the normalize normals SMaterial flag and let the hardware fix them.
If that's not the problem, perhaps you can post the contents of the MTL file here
Yeap.
I manually inspected the .obj normals and the look like they have a unit length (1.0).
Looking deeper at the issue, I found this chunk of code (same for D3D8 and OpenGL).

Code: Select all

void CD3D9Driver::addDynamicLight(const SLight& dl)
{
	if ((u32)LastSetLight == Caps.MaxActiveLights-1)
		return;

	CNullDriver::addDynamicLight(dl);

	D3DLIGHT9 light;

	if ( dl.Type == ELT_POINT )
	{
		light.Type = D3DLIGHT_POINT;
		light.Position = *(D3DVECTOR*)((void*)(&dl.Position));
	}
	else
	if ( dl.Type == ELT_DIRECTIONAL )
	{
		light.Type = D3DLIGHT_DIRECTIONAL;
		light.Direction = *(D3DVECTOR*)((void*)(&dl.Position));
	}

	light.Diffuse = *(D3DCOLORVALUE*)((void*)(&dl.DiffuseColor));
	light.Specular = *(D3DCOLORVALUE*)((void*)(&dl.SpecularColor));
	light.Ambient = *(D3DCOLORVALUE*)((void*)(&dl.AmbientColor));
	light.Range = MaxLightDistance;

	light.Attenuation0 = 0.0f;
	light.Attenuation1 = 1.0f / dl.Radius;
	light.Attenuation2 = 0.0f;

	++LastSetLight;
	pID3DDevice->SetLight(LastSetLight, &light);
	pID3DDevice->LightEnable(LastSetLight, true);
}
It's setting the linear attenuation based on the radius and the constant to 0. I think that's not quite the anticipated effect and responsible for the overbrightness.

For light attenuation values k0 k1 k2, the attenuation calculation is:

attenuation = 1.0 / (k0 + k1 * d + k2 * d^2)

So here's what happening.

Image

blue - Constant attenuation.
purple - What's happening now. Instead of the light fading to black at the Radius, it's actually causing the light near the source become super brightened.
yellow - Closer to what I anticipated the system would work, fading from 1 near the source to 0 at the Radius.

Would it be possible to expose the attenuation values through the SLight structure? I don't know if the current setup is the intended lighting, but it would be nice to be able to override it so I can get the lighting I'm after.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Exposure is planned for the next time, together with Spot lights implementation. But maybe we should change the default to a better value anyway?
nullterm
Posts: 14
Joined: Tue Feb 27, 2007 12:36 pm

Post by nullterm »

That's cool. I look forward to the next release.

I would have expected default values of

Code: Select all

   light.Attenuation0 = 1.0f;
   light.Attenuation1 = 0.0f;
   light.Attenuation2 = 0.0f;

Those are the system defaults (atleast for OpenGL) and most commonly used values.

Here's what my scene looks like after I changed the attenuation to those values and recompiled the Irrlicht.dll. The difference is pretty significant and how I expected the lighting to work.

Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

I'll check for default values in D3D then. My impression when I first saw those numbers (the default values are probably ever since...) was that these are better suited for interactive scenes where you can walk through. Since the light intensity does not change with the default values it's not realistic then!?
lester
Posts: 86
Joined: Mon Jan 29, 2007 3:33 pm

Post by lester »

Oh great, I have the same problem, but I thought that is vertex shaders problem.

http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=18856

I'll try your hint later
nullterm
Posts: 14
Joined: Tue Feb 27, 2007 12:36 pm

Post by nullterm »

hybrid wrote:I'll check for default values in D3D then. My impression when I first saw those numbers (the default values are probably ever since...) was that these are better suited for interactive scenes where you can walk through. Since the light intensity does not change with the default values it's not realistic then!?
The DirectX SDK says "Typically, an application sets Attenuation0 to 0.0, Attenuation1 to a constant value, and Attenuation2 to 0.0."

The DirectX SDK was smart by not giving a specific number as a default. If you tried putting in a specific default for Atten1 or Atten2, then the lighting for a scene will be completely different depending on what game units they use (meters, cm, mm, feet, inches, etc). The "constant value" they mention for Attenuation1 will always be application specific.

I think using the OpenGL defaults (1,0,0) is the smartest choice. It will work consistently for all cases regardless of world units/scale. And if someone wants the attenuation to work in a specific way then they can always override the default values.
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

hey... can you send me the dll? i am having this problem too. :cry:
I am not a typical programmer (i am artist) so i can't change the value myself.
by the way another question: is it suitable to call the primitives as no. of triangles? what it usually call? no. of primitives?

Before adding a light source...
Image

After added the light source... ahh! Not looking good... :cry:
Image
RVL
Posts: 5
Joined: Sat Jun 09, 2007 11:12 am

Possible solution

Post by RVL »

I've met the same problem and made the following changes.

1. New member to SLight class
vector3df Attenuation;//defaults (0.f,0.f,0.f) in constructor
2. Adding appropriate attribute serialize/deserialize methods in CLightSceneNode class
3. Modification of light attenuation logic in drivers' classes (CD3D8Driver.cpp, CD3D9Driver.cpp, COpenGLDriver.cpp, CSoftwareDriver2.cpp) to the following:

Code: Select all

if (light.Attenuation.getLength()==0)
{
  //use native Irrlicht attenuation
}
else
{
  //use standard OpenGL/Direct3D attenuation factor 1/(a0+a1*d+a2*d^2), where
  //a0 = light.Attenuation.X
  //a1 = light.Attenuation.Y
  //a2 = light.Attenuation.Z
}
By default the changes above doesn't affect existing Irrlich attenuation logic. If someone wants he may setup Attenuation member via ILightSceneNode::setLightData() to get standard OpenGL/Direct3D behavior.
ansu832001
Posts: 95
Joined: Thu Mar 01, 2007 6:39 am

Post by ansu832001 »

Hi All,

Iam facing problem with lighting,my nodes(which are of different color from Light)are getting effected,i.e whenever i enable light their actual color is getting effected by color of light.

If iam not wrong this can be done setting Attenuation to default values as said by "nullterm",if so i tried doing that but could not find as where we can set this Attenuation

i already have a thread here http://irrlichtnetcp.sourceforge.net/ph ... .php?t=790

since this lighting problem is generic i am posting here aswell.

Best Regards
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The attenuation is set in the drivers. Up to Irrlicht 1.3.1 this was fixed and you could only change it to some new fixed values by recompiling Irrlicht.
The next Irrlicht version will have an attenuation vector in the SLight data which allows for dynamic changes of the values. You can try it in the SVN version of Irrlicht, but probably not with Irrlicht.CP.
nullterm
Posts: 14
Joined: Tue Feb 27, 2007 12:36 pm

Post by nullterm »

Awesome news. That's very well timed. When will the next official release occur?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Don't know, usually about 2-3 month after the last.
nullterm
Posts: 14
Joined: Tue Feb 27, 2007 12:36 pm

Post by nullterm »

UPDATE - With the new 1.4 beta the light attenuation is just what I needed. The default values match exactly my needs, and the attenuation factors are now exposed so I can modify them if needed.

Big thank you!
Post Reply