Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 16 Oct 2006
Offline Last Active Sep 05 2014 11:35 AM

Posts I've Made

In Topic: Efficient Omnidirectional Shadow Maps (ShaderX3)

22 November 2013 - 12:39 PM

The larger frustum on the right was meant to be the camera, the one on the left was for the light. I guess I should have made that more clear biggrin.png


The algorithm you described earlier says to choose the camera planes that the light is in front of, in this case they are A, B, and C. The red object is also in front of all these planes and it is contained in the light frustum so it would pass all the plane tests and need to be rendered. 


In Topic: Efficient Omnidirectional Shadow Maps (ShaderX3)

22 November 2013 - 02:00 AM

I think the part I was missing in the implementation from the article is that the object shadow frustum doesn't have to actually originate at the light position, the near plane can be pushed all the way to the edge of the object's bounding box/sphere, which makes it a much tighter fit to the area where the shadow can be cast.


Here's another picture showing one of these object frusta in green. I think this also shows a case where your algorithm will identify the object as needing to be drawn when it actually casts a shadow that is not visible to the view frustum.

In Topic: Efficient Omnidirectional Shadow Maps (ShaderX3)

21 November 2013 - 10:16 PM

I see. Your algorithm definitely seems more efficient than what I've been working on. I tried to implement what you just described and I'm getting fewer objects culled than I had previously though. I implemented it like this:

static void GetVisibleForPointLight(BoundingFrustum const & viewfrustum, ForwardPoint const * light, BoundingFrustum const & lightFrustum, GeometryList const & everything, GeometryList & visible)
	Plane planes[12];
	int count = 0;

	for (int i = 0 ; i < 6 ; i++)
		if (viewfrustum.Planes[i].DotCoordinate(light->Position()) > 0.0f)
			planes[count++] = viewfrustum.Planes[i];

	Memory::Copy(&planes[count], lightFrustum.Planes, 6);
	count += 6;

	for (auto o = everything.Begin() ; o != everything.End() ; ++o)
		BoundingSphere const & s = (*o)->WorldBound();
		int inFront = 0;
		for (int i = 0 ; i < count ; i++)
			if (planes[i].DotCoordinate(s.Center) < -s.Radius)


		if (inFront == count)

I'm calling this once per light direction rather than for all directions at once, otherwise I would have to frustum test the objects again per direction (if I'm not mistaken) since not all the objects are visible in each direction.


In my old method (that I was trying to implement from the ShaderX article) I was computing the light -> object frustum for each object and testing that against the camera frustum and putting everything in one big list and then culling per direction again. 


There are about 300 objects in the scene I'm testing and I'm seeing the new version culling anywhere from 20-30 fewer objects up to more than 100 for some camera orientations. In both cases everything looks correct so it's not incorrectly culling anything. Maybe I have an error in my code somewhere though. 

In Topic: Efficient Omnidirectional Shadow Maps (ShaderX3)

21 November 2013 - 08:03 PM

Ok that makes sense, thanks. I was also just generally interested in understanding what this article was describing because it's presented like: you calculate this special frustum for each object and just do a frustum-frustum test against the view frustum and that's it. I think if you construct the cone/frustum described in those sentences I quoted and then extend it to the light's far clip plane it should enclose any possible shadow cast by the object. But it doesn't account for the case shown in the picture so I guess an extra test like what you described is needed. 

In Topic: OpenGL Windows Question

08 October 2013 - 06:51 PM

At a minimum on Window you should use GLEW. There are no system headers/libs for accessing modern OpenGL on Windows so you need to query every function at runtime using wglGetProcAddress. GLEW automates all of this, it queries all the function pointers your card supports and puts them in global function pointers so you can use it like a regular C API. It also provides a header with all the typedefs and constants you'll need to work with these functions.


It's worth pointing out that gDebugger is basically a legacy application now. It was purchased by AMD and has been integrated into their CodeXL profiler/debugger.