Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3D Shadow implementation idea

Lets assume your eye is in the surface point P1 on an object A and there is a target object B and there is a point-light source behind object B.

Question: am i right if i look to the light source and say "i am in a shadow" if i cannot see the light because of object B ?. Then i flag that point of object A as "one of the shadow points of B on A" .

enter image description here

If this is true, then can we build a "shadow geometry"(black-colored) object on the surface of A then change it constantly because of motion of light,B,A, etc... in realtime ? Lets say a sphere(A) has 1000 vertices and other sphere (B)has 1000 vertices too, so does this mean 1 milion comparations? (is shadowing, O(N^2) (time) complexity?). I am not sure about the complexity becuse the changing the P1(eye) also changes the seen point of B (between P1 and light source point). What about the second-order shadows and higher (such as lights being reflecting between two objects many times) ?

I am using java-3D now but it doesnt have shadow capabilities so i think of moving to other java-compatible libraries.

Thanks.

Edit: i need to disable the "camera" when moving the camera to build that shadow. How can i do this? Does this decrease the performance badly?

New idea: java3D has built-in collision detection. I will create lines(invisible) from light to target polygon-vertex then check for a collision from another object. If collision occurs, add that vertex corrd. to the shadow list but this would work only for point-lights :( .

Anyone who supplys with a real shade library for java3d, will be much helpful.

Very small sample Geomlib shadow/raytracing in java3D would be the best Ray-tracing example maybe?

I know this is a little hard but could have been tried by at least a hundred people.

Thanks.

like image 943
huseyin tugrul buyukisik Avatar asked Aug 27 '12 11:08

huseyin tugrul buyukisik


3 Answers

Shadows is probably the most complex topic in 3D graphics programming, and there are many approaches, but the best option should be identified according to the task requirements. The algorithm you are talking about is the simplest way to implement shadows from a spot light source onto the plane. It should not be done on the CPU, as you already use GPU for 3D rendering.

Basically the approach is to render the same object twice: once from the camera view point, and once from the light source point. You will need to prepare model view matrices to convert between these two views. Once you render the object from the light point, you get the depth map, in which each point lies closest to the light source. Then, for each pixel of the normal rendering, you should convert its 3D coordinates into the previous view, and check against the corresponding depth value. This essentially gives you a way to tell which pixels are covered by shadow.

The performance impact comes from rendering the same object twice. If your task doesn't assume high scalability of shadow casting solution, then it might be a way to go.

A number of relevant questions:

How Do I Create Cheap Shadows In OpenGL?

Is there an easy way to get shadows in OpenGL?

What is the simplest method for rendering shadows on a scene in OpenGL?

like image 122
Tosha Avatar answered Oct 12 '22 10:10

Tosha


Your approach can be summarised like this:

foreach (point p to be shaded) {
    foreach (light) {
        if (light is visible from p)
            // p is lit by that light
        else
            // p is in shadow
    }
}

The funny fact is that's how real-time shadows are done today on the GPU.

However it's not trivial for this to work efficiently. Rendering the scene is a streamlined process, triangle-by-triangle. It would be very cumbersome if for every single point (pixel, fragment) in every single triangle you'd need to consider all other triangles in other to check for ray intersection.

So how to do that efficiently? Answer: Reverse the process.

There's a lot fewer lights than pixels on the scene, usually. Let's take advantage of this fact and do some preprocessing:

// preprocess
foreach (light) {
    // find all pixels p on the scene reachable from the light
}
// then render the whole scene...
foreach (point p to be shaded) {
    foreach (light) {
        // simply look up into what was calculated before...
        if (p is visible by the light)
            // p is lit
        else
            // p is in shadow
    }
 }

That seems a lot faster... But two problems remain:

  1. how to find all pixels visible by the light?
  2. how to make them accessible quickly for lookup during rendering?

There's the tricky part:

  • In order to find all points visible by a light, place a camera there and render the whole scene! Depth test will reject the invisible points.
  • To make this result accessible later, save it as a texture and use that texture for lookup during the actual rendering stage.

This technique is called Shadow Mapping, and the texture with pixels visible from a light is called a Shadow Map. For a more detailed explanation, see for example the Wikipedia article.

like image 41
Kos Avatar answered Oct 12 '22 09:10

Kos


Basically yes, your approach will produce shadows. But doing it point by point is not feasible performance wise (for realtime), unless its done at the GPU. I'm not familiar with what the API's offer today, but I'm sure any recent engine will offer some shadow out of the box.

Your 'New idea' is how shadows were implemented back in the days when rendering was still done with the CPU. If the number of polygons isn't too big (or you can efficently reject entire bunches by having grouping volumes etc.) it can be done with fairly little CPU power.

like image 1
Durandal Avatar answered Oct 12 '22 09:10

Durandal