# The Industry's Foundation for High Performance Graphics

1. ## Calculating where the shadow falls on a plane

Hi all,

I am new to OpenGL and it's some time that I started programming with JOGL and JCUDA (OpenGL and Cuda porting on Java)

I would need to calculate the shadow of a 3d model on a plane. Models can be also 5 milions triangles while the plane is basically a square that ranges from 480 to 4800 tiles.

I already managed to draw the 3d model with OpenGL and calculate the projection of each triangle on the plane with CUDA.

The big problem for me arises when I want to know which tiles are covered by the shadow and which ones arent. If I draw the array of the projected triangle I have the result printed on the screen, but I need somehow to manage it (an idea would be to retrieve the result like a boolean matrix).

For example, a projected triangle on a 4x4 matrix could appear like the following:

0100
0110
0111
0000

1 means I have shadow on that tile, 0 means no shadow

I read a lot about rastering, ray tracing, FBOs, stencil buffer, etc...

But since I am a newbie on this field, I am very confused and so I would like to ask you which is the best idea to reach this goal.

2. ## Re: Calculating where the shadow falls on a plane

If I draw the array of the projected triangle I have the result printed on the screen, but I need somehow to manage it
This part is not clear to me. What do you actually want to do? Render your model such that it casts a shadow onto the plane or do you need e.g. the size of the area of the projection?

Rendering shadows is a huge topic, with a large number of techniques. Most are variations of either "shadow volumes" (basically extrudes silhouette edges in light direction and renders that into the stencil buffer, then uses the stencil to determine where light is reflected) or "shadow maps" (basically render the scene from the light's point of view, and compare distance of a camera fragment with distance of closest object from light to decide if the fragment is lit).

3. ## Re: Calculating where the shadow falls on a plane

Originally Posted by carsten neumann
If I draw the array of the projected triangle I have the result printed on the screen, but I need somehow to manage it
This part is not clear to me. What do you actually want to do? Render your model such that it casts a shadow onto the plane or do you need e.g. the size of the area of the projection?

sorry if my english is not good , however I would need to cast the shadow on the plane and retrieving a kind of matrix that represents the plane itself and where each tiles is boolean (that is, shadow or not)

At the moment I have somehow calculated the shadow by just projecting each triangle on the plane. At this point I'd need to rasterize it... but it appears like an hard job compared to OpenGL, where it's pretty easy and it rasterize them automatically. The problem is that the OpenGL output is only displayed on the screen.. while I'd need instead in a boolean matrix for example

4. ## Re: Calculating where the shadow falls on a plane

One way to do this is to create a FBO (frame buffer object) that has the dimensions of your plane. You'd then set up rendering to go into that FBO instead of the usual application buffers (that are displayed on the screeen) and have your modelview/projection matrices perform the projection of triangles onto the plane. Clear the FBO to white, enable GL_MIN blending (glBlendEquation(GL_MIN)) and render the triangles in black. Then use glReadPixels() to read back the data to main memory or another buffer on the GPU (that buffer could use CUDA/GL interop to be shared with CUDA) depending on where you need to process the information. Black pixels are in shadow, white ones are not.

Information on how to use FBOs can be found on the OpenGL wiki: FBO for example.

5. ## Re: Calculating where the shadow falls on a plane

Originally Posted by carsten neumann
One way to do this is to create a FBO (frame buffer object) that has the dimensions of your plane. You'd then set up rendering to go into that FBO instead of the usual application buffers (that are displayed on the screeen) and have your modelview/projection matrices perform the projection of triangles onto the plane. Clear the FBO to white, enable GL_MIN blending (glBlendEquation(GL_MIN)) and render the triangles in black. Then use glReadPixels() to read back the data to main memory or another buffer on the GPU (that buffer could use CUDA/GL interop to be shared with CUDA) depending on where you need to process the information. Black pixels are in shadow, white ones are not.

Information on how to use FBOs can be found on the OpenGL wiki: FBO for example.
After days spent looking for answer this looks the right solution! Thanks Carsten tomorrow I will try to apply it

6. ## Re: Calculating where the shadow falls on a plane

I am a little confused

Do I need to render to texture anyway?
Which attachment should I use? The color?
What should I attach to the framebuffer, a texture image or a renderbuffer image?

Unfortunately I didnt found any example that show clearly how to render off screen and save it as an image

( This user looks to had the same problem)

7. ## Re: Calculating where the shadow falls on a plane

Here at the end it says it doesnt matter if I attach a renderBuffer or a texture

Do you have any suggest on which way should I use?

8. ## Re: Calculating where the shadow falls on a plane

Ok, I decided to opt for a renderBuffer

here my code so far

Code :
```private void renderShadows(GL2 gl)    {
//  creating the FBO
int[] frameBufferID = new int[1];
gl.glGenBuffers(1, frameBufferID, 0);

// bounding the FBO
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);

// creating the RenderBuffer Object
int[] renderBufferID = new int[1];
gl.glGenRenderbuffers(1, renderBufferID, 0);

// bounding the RBO
gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, renderBufferID[0]);

// Allocate the RBO
gl.glRenderbufferStorage(GL2.GL_RENDERBUFFER, GL2.GL_RGB, floorWidth, floorHeight);

// Attaching the RB image (RBO) to the FBO
gl.glFramebufferRenderbuffer(GL2.GL_FRAMEBUFFER, GL2.GL_COLOR_ATTACHMENT0,
GL2.GL_RENDERBUFFER, renderBufferID[0]);

if(gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER) == GL2.GL_FRAMEBUFFER_COMPLETE)
System.out.println("GL_FRAMEBUFFER_COMPLETE!!");
else
System.out.println("..[censored] ^^");
}```

And so far it works , I get the frameBuffer complete

But how can I go further now? How do I clean the FBO to white? And what about the pixel format?

9. ## Re: Calculating where the shadow falls on a plane

Code :
```// save the current viewport and set the new
gl.glPushAttrib(GL2.GL_VIEWPORT_BIT);
gl.glViewport(0, 0, floorWidth, floorHeight);

// bind the FBO
gl.glBindFramebuffer(GL2.GL_DRAW_FRAMEBUFFER, frameBufferID[0]);

int[] attachmentID = new int[1];
attachmentID[0] = GL2.GL_COLOR_ATTACHMENT0;
gl.glDrawBuffers(1, attachmentID, 0);

// clear
gl.glClear(GL2.GL_COLOR_BUFFER_BIT);

gl.glBlendEquation(GL2.GL_MIN);

gl.glColor3f(0.0f, 0.0f, 0.0f);

// render
gl.glBegin(GL2.GL_TRIANGLES);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glVertex3f(1.0f, 0.0f, 0.0f);
gl.glVertex3f(0.0f, 0.0f, 0.0f);
gl.glEnd();

gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
gl.glDrawBuffer(GL2.GL_BACK);

//  restore viewport
gl.glPopAttrib();```

How can I render the FBO content on the screen to check it?

This doesnt work:
Code :
```gl.glBindFramebuffer( GL2.GL_FRAMEBUFFER, frameBufferID[0] );
gl.glDrawBuffer(GL2.GL_COLOR_ATTACHMENT0);
gl.glViewport( 0, 0, floorWidth, floorHeight );
//gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glClear( GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );```

10. ## Re: Calculating where the shadow falls on a plane

If you attach a texture instead of a render buffer you can then use that texture on a quad rendered to the application frame buffer to look at it. Or you use glReadPixels() to transfer the pixels to main memory and write an image file.

Is that last snippet meant to render to the screen? It binds the FBO and sets GL_COLOR_ATTACHMENT0 as draw buffer, so it draws to the FBO. To render to an application frame buffer, unbind the FBO (glBindFrameBuffer(GL_FRAMEBUFFER, 0)) and set the draw buffer to GL_BACK.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•