Problem with multiple shadow casting lights

Problems building or running the engine, queries about how to use features etc.
Post Reply
chaos creator
Gnoblar
Posts: 22
Joined: Tue May 08, 2012 5:56 pm
x 4

Problem with multiple shadow casting lights

Post by chaos creator »

I implemented integrated texture shadows and they're working pretty well... exept for one strange behaviour.
The testing scene is a big model + the player being able to move on top on it. When one spotlight is being used, everything works fine. The player casts shadows on the model and vice versa, self shadows work too.
But as I added more lights i noticed strange shadows on the Player. So I added debug code to the reciever shader, you can see the result in the attachment.

The different colored squares on the floor are the spotlights view frustrum, I only check wether each pixel lies inside of the shadows UV coordinates [0..1].
On the floor all lights are visible, including the shadows (which is basically the same). But on the player... you can only see the blue light, but only the part which would get lit from the red spotlight.

If the player is inside the red spot, the shadow is nearly all the time drawn correctly (exept inside the overlapping parts of the lights), while this is not the case with any other light. But as I disabled it, the same behaviour occurred with the next nearest light. So I thought it was a error with not all passes of the multipass material being rendered. To test wether the material gets rendered for every light i just outputtet in each pass the light colour - and it worked like it should.

So I'm really confused now... if the Object is big enough for being visible for all lights, all lights are being rendered correctly. But if not, it seems like only the light it spawns at (or the light nearest to the origin?) is being renderd correctly.

Code: Select all

material TestMat
{
	technique
	{
		pass
		{
			vertex_program_ref ambient_vs
			{
			}
			fragment_program_ref ambient_ps
			{
			}
			texture_unit
			{
				texture TestMap.png
			}
		}
		pass
		{
			iteration once_per_light
			scene_blend add
		
			vertex_program_ref perLight_vs
			{
			}
			fragment_program_ref perLight_ps
			{
			}
			texture_unit
			{
				content_type shadow
				filtering none
			}
			texture_unit
			{
				texture TestMap.png
			}
		}
	}
}

Code: Select all

float4x4 WVPM;
float4x4 texViewProj;
float4x4 world;

struct VS_INPUT 
{
	float4 Position : POSITION0;
	float2 UV : TEXCOORD0;
	float3 Normal : NORMAL;
};

struct VS_OUTPUT 
{
	float4 Position : POSITION0;
	float2 UV : TEXCOORD0;
	float3 lightPos : TEXCOORD1;
	float3 Normal : TEXCOORD2;
	float4 ShadowUV : TEXCOORD3;
};

VS_OUTPUT perLight_vs( VS_INPUT Input )
{
	VS_OUTPUT Output;
	
	Output.Position = mul( WVPM, Input.Position );
	Output.UV = Input.UV;
	Output.lightPos = lightPos.xyz - Input.Position.xyz;
	Output.Normal = Input.Normal;
	
	float4 worldPos = mul(world, Input.Position);
	Output.ShadowUV = mul( texViewProj, worldPos );
	
	return( Output );
}


float4 lightColour;
float3 lightDir;
float4 spotParams;
sampler2D tex: register(s1);
sampler2D shadowMap: register(s0);


struct PS_INPUT 
{
	float2 UV : TEXCOORD0;
	float3 relLightPos : TEXCOORD1;
	float3 Normal : TEXCOORD2;
	float4 ShadowUV : TEXCOORD3;
};

float4 perLight_ps( PS_INPUT Input ) : COLOR
{
	Input.ShadowUV = Input.ShadowUV / Input.ShadowUV.w;
	if (Input.ShadowUV.x > 0 && Input.ShadowUV.x < 1 && Input.ShadowUV.y > 0 && Input.ShadowUV.y < 1)
		return tex2D( tex, Input.UV ) * (lightColour * LdotN / dSqr);
	else
		return float4(0,0,0,1);
}
This is the code without the shadow part, but it should be enough to reproduce the error.
It seems like everything works exept the UV coordinates of the Shadow map.
Attachments
Example.png
chaos creator
Gnoblar
Posts: 22
Joined: Tue May 08, 2012 5:56 pm
x 4

Re: Problem with multiple shadow casting lights

Post by chaos creator »

Example.m4v

I'll try to demonstrate better what exactly happens.

The .material file is as follows:

Code: Select all

vertex_program perLightTest_vs hlsl
{
	source Shader2.hlsl
	entry_point perLight_vs
	target vs_3_0
	
	default_params
	{
		param_named_auto worldViewProj worldviewproj_matrix
		param_named_auto lightPos light_position_object_space 0
		param_named_auto texWorldViewProj texture_viewproj_matrix 0
	}
}
 
fragment_program perLightTest_ps hlsl
{
	source Shader2.hlsl
	entry_point perLight_ps
	target ps_3_0
	
	default_params
	{
		param_named_auto lightColour light_diffuse_colour 0
	}
}
 
material Test
{
	technique
	{
		pass
		{
			vertex_program_ref ambient_vs
			{
			}
			fragment_program_ref ambient_ps
			{
			}
		}
		pass
		{
			iteration once_per_light
			scene_blend add
		
			vertex_program_ref perLightTest_vs
			{
			}
			fragment_program_ref perLightTest_ps
			{
			}
			texture_unit
			{
				content_type shadow
				filtering none
			}
		}
	}
}
HLSL Shader:

Code: Select all

float4x4 worldViewProj;
float4 lightPos;
float4x4 texWorldViewProj;

struct VS_INPUT 
{
	float4 Position : POSITION0;
};

struct VS_OUTPUT 
{
	float4 Position : POSITION;
	float3 relLightPos : TEXCOORD0;
	float4 ShadowUV : TEXCOORD1;
};

VS_OUTPUT perLight_vs( VS_INPUT Input )
{
	VS_OUTPUT Output;
	
	Output.Position = mul( worldViewProj, Input.Position );
	Output.relLightPos = lightPos.xyz - Input.Position.xyz;
	Output.ShadowUV = mul( texWorldViewProj, Input.Position );
	
	return( Output );
}

float4 lightColour;

struct PS_INPUT 
{
	float3 relLightPos : TEXCOORD0;
	float4 ShadowUV : TEXCOORD1;
};

float4 perLight_ps( PS_INPUT Input ) : COLOR
{
	float dSqr = dot( Input.relLightPos, Input.relLightPos );
	
	float4 shadowUV = Input.ShadowUV / Input.ShadowUV.w;
	
	if (shadowUV.x > 0 && shadowUV.x < 1 && shadowUV.y > 0 && shadowUV.y < 1)
		return lightColour / dSqr;
	else
		return float4(0,0,0,0);
}
It does nothing exept returning the light's colour when inside the shadow's area.
But as you can see in the attached video, it only works for the ground. It just seems like the cube doesn't get the correct texture_viewproj_matrix before it leaves the light completly.
I do exept that those matrices are only correctly set for lights which affect the object, but they're getting "disabled" too early. Nevertheless the according light passes are executed, as I saw by another test.
chaos creator
Gnoblar
Posts: 22
Joined: Tue May 08, 2012 5:56 pm
x 4

Re: Problem with multiple shadow casting lights

Post by chaos creator »

Didn't saw how crappy file-upload is, sorry :D

But the problem remains unsolved.
I already tried making a single-pass material, it's still the same.
Hopefully the problem gets more visible in the new screenshots.
All there is is one model as the static "world" at (0,0,0), a second one, a movable cube and two lights, a blue and an orange one at (-3, 10, 0) and (3, 10, 0), which should be totally fine.
The rectangles on the floor are what would be lit by the two lights, which is everything where the shadow UV is inside [0..1].
I use the same shaders, so the calculation for the UV coordinates is just mul(shadow-texture-world-view-proj-matrix, vertex-position)

There are cases where it works how it should:
Img3.png
You can see that the cube is being lit by both lights at the left side but only the blue light at the right side, which is nice.
Inside the blue light it is always correctly lit.
But if you move far enough away from the blue light inside the orange one...
Img1.png
It's outside from the orange's shadow-uv coordinates. BUT the orage light still affects it, the pass is being executed, like another shader showed!

And the stangest of all:
Img5.png
It seems like it's getting lit by the blue light while with the orange light's colour...
Since the only thing being messed up seems to be the texture matrix, I assume that the pass for the orange light receives the blue light's texture matrix while the blue light's pass doesn't get any matrix at all (or Matrix::IDENTITY, probably)


So I'm no step further, only convinced that there's something wrong with the shadow camera's matrices being sent to the shader.
Changing things like the shadow far distance or similar functions didn't do anything. If anyone has any suggestions or ideas, I'd be really glad to hear them because I have no clue what I could do anymore.
chaos creator
Gnoblar
Posts: 22
Joined: Tue May 08, 2012 5:56 pm
x 4

Re: Problem with multiple shadow casting lights

Post by chaos creator »

As I made no progress, I've tried building a new application from scratch, only containing the problematic part.
Since I was still using 1.9.0unstable I've also downloaded the stable version, which didn't change anything.

Here's the whole code:

Code: Select all

#include "OgreRoot.h"
#include "OgreRenderWindow.h"
#include "OgreConfigFile.h"
#include "OgreSceneManager.h"
#include "OgreCamera.h"
#include "OgreEntity.h"
#include "OgreWindowEventUtilities.h"
using namespace Ogre;


void main()
{
	Root* root = new Root("Plugins.cfg", "Config.cfg", "OgreLog.txt");
	RenderWindow* window;
	SceneManager* sceneMgr;
	Camera* camera;

	if (!root->showConfigDialog())
		return;

	window = root->initialise(true, "Material Test");

	ConfigFile cf;
	cf.load("Media.cfg");
	ConfigFile::SectionIterator seci = cf.getSectionIterator();
	String secName, typeName, archName;
	while (seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		ConfigFile::SettingsMultiMap *settings = seci.getNext();
		ConfigFile::SettingsMultiMap::iterator i;
		for (i = settings->begin(); i != settings->end(); ++i)
		{
			typeName = i->first;
			archName = i->second;
			ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
		}
	}
	ResourceGroupManager::getSingleton().initialiseAllResourceGroups();



	sceneMgr = root->createSceneManager("DefaultSceneManager", "SceneMgr");
	camera = sceneMgr->createCamera("MainCam");
	Viewport* viewport = window->addViewport(camera);
	viewport->setBackgroundColour(ColourValue(.1, .1, .1));
	sceneMgr->setAmbientLight(ColourValue::Black);

	sceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
	sceneMgr->setShadowTextureSelfShadow(true);
	sceneMgr->setShadowCasterRenderBackFaces(false);
	sceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
	sceneMgr->setShadowTextureSize(2048);
	sceneMgr->setShadowTextureCount(2);
	sceneMgr->setShadowTextureCasterMaterial("DepthShadowCaster");
	sceneMgr->setShadowFarDistance(100);

	camera->setAutoAspectRatio(true);
	camera->setPosition(0, 10, 5);
	camera->lookAt(0, 0, 0);
	camera->setProjectionType(PT_PERSPECTIVE);
	camera->setFOVy(Degree(100));
	camera->setNearClipDistance(1);
	camera->setFarClipDistance(100);

	Entity* ent = sceneMgr->createEntity("Plane.mesh");
	ent->setMaterialName("Test");
	SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode();
	node->attachObject(ent);


	SceneNode* lightNode = sceneMgr->getRootSceneNode()->createChildSceneNode();


	Light* light1 = sceneMgr->createLight();
	light1->setType(Light::LT_SPOTLIGHT);
	light1->setDiffuseColour(ColourValue(80, 40, 0));
	lightNode->attachObject(light1);
	light1->setPosition(2, 10, 0);
	light1->setDirection(0, -1, 0);
	light1->setSpotlightRange(Degree(40), Degree(40));

	Light* light2 = sceneMgr->createLight();
	light2->setType(Light::LT_SPOTLIGHT);
	light2->setDiffuseColour(ColourValue(0, 40, 80));
	lightNode->attachObject(light2);
	light2->setPosition(-2, 10, 0);
	light2->setDirection(0, -1, 0);
	light2->setSpotlightRange(Degree(40), Degree(40));

	for (int i = -8; i <= 8; i += 2)
	{
		Entity* cube = sceneMgr->createEntity("PlayerCube.mesh");
		cube->setMaterialName("Test");
		SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(i, .9, 0));
		node->attachObject(cube);
	}

	for (int i = -8; i <= 8; i += 2)
	{
		Entity* cube = sceneMgr->createEntity("PlayerCube.mesh");
		cube->setMaterialName("Test");
		SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, .9, i));
		node->attachObject(cube);
	}


	while (true)
	{
		if (window->isClosed())
			return;

		lightNode->yaw(Degree(1.5));

		root->renderOneFrame();
		WindowEventUtilities::messagePump();
	}
}
- to me it seems like there couldn't be anything wrong. The material / shader being used is still the same (well, it's a single pass version, but there are no differences)

When the cubes / the camera rotate, the (wrong) behaviour is stable. But when only the lights get rotated, a strange but predictable pattern appears:
https://vimeo.com/106103170 (I seem to be unable to embed the video :D)

Now I'll try passing the matrices manually, if it works it has to be a bug in Ogre... that somehow managed it to be this long undetected which is the oddest thing of all
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Problem with multiple shadow casting lights

Post by dark_sylinc »

Ahhhhh, a video says a million words.

I've fixed a couple if minor bugs in 2.0 regarding shadowing; it's hard to get it 100% right.
It appears those "columns" could have wrong AABB. How is the scene composed? (i.e. how many entities there are, or a breakdown of the rendering procedure)

Also try setting your material's shadow's texture units to addressing mode border colour 1 1 1 1
chaos creator
Gnoblar
Posts: 22
Joined: Tue May 08, 2012 5:56 pm
x 4

Re: Problem with multiple shadow casting lights

Post by chaos creator »

The bounding boxes are set correctly (which sceneNode->showBoundingBox(true) visualises).
But it definitely looks like a culling error... but the AABBs are set correctly.

Maybe it helps to post anything related:

Source code: http://pastebin.com/22h2YaiY

ShadowCaster .material: http://pastebin.com/xgcpejMC
ShadowCaster .hlsl: http://pastebin.com/2Dy9U0hJ

Material: http://pastebin.com/9MQkexM6
Shader: http://pastebin.com/h5RjCRJK

There's only one ground plane (16x16, centered around 0,0,0) and cubes (0.6 x 0.6 x 1.8), in two rows orientated along the x / z axis - 9 cubes each.

I modified the shader to show wether a point is inside the shadow map AND wether the pass is being executed at all. The result of the first test is the same as previous, the second one shows that the pass for a light is executed even when the object doesn't receive the texture_worldviewproj_matrix, but even there it gets culled too early. But after all this seems to be the same culling problem as with the shadowUVs.

If you think it's a problem with Ogre 1.9 I could try moving to Ogre 2.0.
But what really confuses me is that this seems like a bug which should be detected ages ago?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Problem with multiple shadow casting lights

Post by dark_sylinc »

Wait, you're using the default camera setup! Try something better, like the Focused shadow camera setup, or PSSM.

The Default Shadow cam. setup is pretty simplistic, and its default parameters are prone to these "glitches" (the problem is basically accuracy and floating point range).
Btw if you're using D3D9, change the floating point mode to "Consistent", not "Fast".
chaos creator
Gnoblar
Posts: 22
Joined: Tue May 08, 2012 5:56 pm
x 4

Re: Problem with multiple shadow casting lights

Post by chaos creator »

Well, I was JUST about to write how it didn't help but... YES! It did!

I tried switching to floating point mode consistent, even scaled up all my models to be sure wether it's an accuracy issue - but it wasn't.
It actually surprised me that the default shadow camera setup wasn't good enough. Because they are still spotlights, so they it should be clear how to render the shadow buffer unlike with directional lights?
So obviously I was wrong...
There are still some entitys not receiving the correct matrix / culled too early it seems like but at the same time the whole shadow camera has a bigger FOV? Right now everything inside the spotlight's cone is rendered correctly which is all that matters. I'll test this in better testing environements and see if this really solved anything, but right now, I think it did.

Thank you for your help!


After applying the FocusedShadowCameraSetup to the main application, it's nearly perfectly fine!
Only in a few rare edge cases there were a few artifacts, but they appear to be negligible.

I'm very happy about the result: 8)
Solved.png
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Problem with multiple shadow casting lights

Post by dark_sylinc »

I'm happy that you were able to fix the bug.
And btw. that scene looks gorgeous.
Post Reply