Light Shader

Started by
39 comments, last by belfegor 10 years, 10 months ago

> You need to manage lights that are not visible or very far away and which contribution is minimal so that you can skip some work.

I checked the code sample "Direct3D 9 Normal Mapping Demo" which is a good example, however it's using one single light in the entire scene, sometimes I will have a mesh which is getting affected by multiple lights at the same time.

Does that means that the project is useless and I must look for other technique such as "deferred rendering" and "light pre pass"? If yes, any deferred rendering shader out there?

Advertisement

Does that means that the project is useless and I must look for other technique such as "deferred rendering" and "light pre pass"? If yes, any deferred rendering shader out there?

It's not useless. You can use normal mapping with almost any lighting technique you want. I would advise against using the deferred techniques for now. They are a lot harder to implement and bring their own problems with them (transparent objects for example). You can't just throw a "deferred rendering shader" on there and expect it to work.

Choosing a lighting technique is an important decision and will fundamentally change the way your rendering pipeline works and performs.

Your choices:

- Multi-pass: Render the object multiple times and apply one light source with each pass.

- "Uber-shader": Multiple lights in one pass plus anything else you might need and enable/disable the parts you need.

- Combination of the above

- Deferred: Render scene to a G-Buffer and calculate lighting independently

What does your typical scene look like? How many lights are we talking? How large are they? How many objects do they affect?

current project: Roa

First of all I want to mention that it's FPS game.

I don't know how many light I will be having in the scene, it depends on the game mission, but I expect many different lights.

For example: I could have 30-40 light in a scene as well as multiple lights affecting many meshes, rendering each mesh 30-40 times is just a total waste of performance.

If you want to listen to me, you should go with forward renderer and multi-pass lights, since you are accustomed with it and it is easiest way.

If you have 30-40 lights in the scene then be smart where do you place them, have 3 or 4 as max light count affecting some object, choose by some priority for example for outdoor scene sun would always be included, player flashlight is priority, then choose rest by distance, cull occluded lights, for point lights test light bounding sphere against objects bounding volume for intersection to see if it should contribute...

From seeing your comments, I can easily see that you aren't happy about the performance happy.png

As other people recommended, you can check whether the object is affected by the light, here's how with a Point Light!

Bounding Spheres

Bounding Spheres is if you were to collect all the vertices in the mesh and make a sphere encapsulate them, like this:

530px-Tighter_bounding_sphere.pngRABBITS!biggrin.png

To get this result, you need two things:

  1. The center of the mesh
  2. The radius of the mesh from the center

Calculating the center:

  • Declare the variable ohmy.png
  • Loop over all your vertices and add them to the center
  • Divide the center by the number of vertices.
  • THAT'S IT!

D3DXVECTOR3 center = D3DXVECTOR3(0, 0, 0);

for(int v = 0; v < mVertices.size(); v++ )
{
    center += mVertices[v];
}

center /= mVertices.size();

Calculating the radius: (With the center)

  • Declare the variable laugh.png
  • Loop over all the vertices
  • Get the distance between the vertices and the center
  • Find the greatest length

float radius = 0.0f;
for (int v = 0; v < mVertices.size(); v ++)
{
    D3DXVECTOR3 diff = mVertices[v] - center;
		
    float length = sqrtf(D3DXVec3Dot(&diff, &diff));

    if (length > radius)
        radius = length;
}

To visualize the result, you just need to translate a sphere (or stuff) to this location: sphere->Translate(mesh->Position + mesh->Center), and also scale it by the meshes radius.

Testing for collision between Sphere-Sphere

As you know the point light has a radius, and so does, hopefully, the mesh with these calculations. To see if they collide, just do the following

  • Find the vector between the mesh center and the point light's position.
  • Get the length of that vector
  • Check whether that length is smaller than both the point light's radius and the mesh's radius.
  • If true, they collide!!!

D3DXVECTOR3 mDistance = mesh->center + pointLight.Position;
float d = sqrtf( D3DXVec3Dot( &mDistance, &mDistance) );

if (d < (mesh->BoundingSphere.radius + pointLight.Range) )
    // They collide!!!

In other words, if they collide, the light will affect the mesh.

Mini Tutorials! laugh.png

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

First of all I want to mention that it's FPS game.

I don't know how many light I will be having in the scene, it depends on the game mission, but I expect many different lights.

For example: I could have 30-40 light in a scene as well as multiple lights affecting many meshes, rendering each mesh 30-40 times is just a total waste of performance.


Lights are additive, so you loop through all lights in the shader and add the outgoing irradiance values for each light. You should read up on lighting and BRDFs if you are serious about having 30-40 lights in a scene.

On a separate note, if you are serious about trying to build a first person shooter game, you are going about it the completely wrong way. Gamedev.net is a great place to ask questions when you already have some idea of what you want, but if you just come in here and ask for code without really a question, you come off as lazy. Then you come here with every single error you receive for code you didn't write, instead of taking some initiative and trying to figure it out on your own. That is why you have received so many downvotes for this thread. There are many resources for learning how to do proper lighting, and shader programming.

If you are serious about learning graphics programming, I highly recommend this book:
http://www.amazon.com/Real-Time-Rendering-Third-Edition-Akenine-Moller/dp/1568814240/ref=sr_1_1_bnp_1_har?ie=UTF8&qid=1370474265&sr=8-1&keywords=real+time+rendering

That's just one of many books you will need if you want to be a graphics programmer.

Best of luck, I hope you soon come to realize that this is the absolute wrong way to ask for help.

Edit - On another note, have you asked yourself whether you even want to be doing the graphics yourself? Consider using an engine that already has done the lighting stuff for you.

@metsfan: Maybe you misunderstood me, I have already done a lot of things other than lights, so I don't really need to start graphics programming from the beginning.

The thing that I don't have experience with is shader, I thought I could use FFP light but I couldn't since I can't use it while using shaders.

I will not use another game engine since I have already programmed almost 60%-70% of the game engine, so it's not wise to just throw what I have done so far away.

BTW, when I ask for code samples, it doesn't mean that I'm lazy, it means that I want to get the idea on how it should be done.

@Migi0027: I have heard I could pass light array to the shader, why would I test for collision? why not just pass the light array and calculate the final light accordingly?

@metsfan: Maybe you misunderstood me, I have already done a lot of things other than lights, so I don't really need to start graphics programming from the beginning.

The thing that I don't have experience with is shader, I thought I could use FFP light but I couldn't since I can't use it while using shaders.

I will not use another game engine since I have already programmed almost 60%-70% of the game engine, so it's not wise to just throw what I have done so far away.

BTW, when I ask for code samples, it doesn't mean that I'm lazy, it means that I want to get the idea on how it should be done.

@Migi0027: I have heard I could pass light array to the shader, why would I test for collision? why not just pass the light array and calculate the final light accordingly?

What he is saying is this: Each point light has an area of influence. Additionally, each light adds complexity to the final shading equation, since the shading equation must be performed for each light. You can cull away lights which do not affect your object, thus increasing performance. This can be done, as he showed, using Sphere-Sphere intersection. One sphere would be the area of influence for the light, the 2nd sphere would be a bounding sphere approximation for your 3D model.

@metsfan: Any examples for passing and processing different kind of LIGHT ARRAY to pixel shader?

@metsfan: Any examples for passing and processing different kind of LIGHT ARRAY to pixel shader?


You can pass your light data to HLSL using a constant buffer.

This topic is closed to new replies.

Advertisement