Lighting and material

Hi,

I have a couple more higher level / design type of questions. Please excuse me if these questions sounds basic or stupid, as I am still fairly new to game development and am still getting the hang of how things work.

I am putting together a basic 3D engine to use for a card game. I have gotten the basics working and have even managed to getsimple shadows working (thanks to @kosmonautgames for the pointers).

However, up to this point I have been using the BasicEffect class and have now started looking into building a real light system (well… since I started looking into shadows).

I am a little confused as to how people approach multiple lights. I understand that there are a couple basic light types viz.

Ambient light general all around lighting
Directional light e.g. Sun
Point lights e.g. light bulbs
Spot lights

My questions are:

How do you figure out how many lights of each type can / should be supported, and how are all the lights “accumulated”? I’ve read a number of differing and confusing options for multiple lights.

Some folk tend to use a single shader which can support an array of light types, but I’ve also read that using branching and loops in shaders is a no-no, so this approach is not ideal (or is this assertion incorrect?).

I’ve also read that some people create separate shaders per light type e.g. PointLightShader.fx etc, and then call each one multiple times for each instance of the light.

There are other confusing topics light light sorting, picking lights based on the ones that impact the model, which lights cast shadows etc.

Then there seems to be a separate issue of how you render lights based on deferred rendering vs. forward rendering.

If you built a lighting system, what was your approach, and why did you choose the way you did? Also did you support both deferred and forward rendering, or did you pick one way and stick with it?

A separate question was regarding the material on a model. I currently don’t see any way to retrieve material information from a model i.e. emissive properties, shininess, diffuse etc. How do people obtain this information? Do you need to write your own custom pipeline processor? Is there a reason material information isn’t defined in the XNA model class?

Thanks in advance!

my god that’s too many questions!

First of all - branching looping etc. are okay today. For reference: In CryEngine they would compile a new shader for each permutation (when creating materials), leading to hundreds of different shaders, but they had no branching.

In the new Doom, where the lead engineer was the previous CryEngine lead engineer, he says they are done with this system and just use dynamic branching in only very few shaders instead, because today branching is pretty well supported on the GPU.

Basically every game today has some sort of screen space effects like for example Screen Space Ambient Occlusion and Reflections. These absolutely, all the time, use looping and often branching too.

That depends on the shading model (forward / deferred). In forward you have to find out yourself basically. It depends on how expensive the lights are and how many model x light variations can exist in the current budget.
If you use stuff like Tiled Lighting or Forward+ you can optimize this a bit.

In a deferred engine, depending on the implementation, hundreds or thousands light sources can be drawn, depending on their size on the screen, but you have some base costs and some limitations with your materials.

I’ve done both. In my actual 3d game - which you can see here https://www.youtube.com/watch?v=tvRTHaPNTyk&t=2s - I have implemented a forward rendering system and I think I support 40 or 60 lights at once. I’ve never tried more, since I didn’t need to. All my bullets etc. casts light, plus headlights, explosions and sun light.

For point lights in a straight forward fashion you can check out this thread: Struggling to find point light resources

For fun I made a deferred engine, too, which you can download here Deferred Engine Playground - download

In my opinion, unless you need a lot of lights, the forward way is easier and much more performant. Plus, if you want to have smoke / transparent things you have to make these parts forward rendered anyways again, so there’s that.

@kosmonautgames

Thanks again for your response. Your game looks pretty cool. What did you use to create the HUD / UI overlay?

I will first try building a full forward rendering light system and see how that works out. Did you fix the number of directional vs. Spot lights etc?

Also, did you end up building all lights into a single shader, or do you have separate shaders for each light type?

I guess it doesn’t make a huge difference… I can start out with separate shaders and look at combining them later for performance reasons.

Also… with regards to managing material… how did you specify the details of what your material properties should be?

Thanks again for the pointers!

I have one directional light only (the sun). For spot vs point lights I save them in the same array but I store the radius as a negative for spotlights and check for that to determine which algorithm to use.

It’s all a single shader for lighting, and since it’s forward rendered, it’s not dependent on light type but on material type.

So the different shaders are only for different types of materials, but the lighting afterwards is all the same.

I use 4 material properties: Diffuse Color (with alpha test), Normal, Roughness, Metallic.

For each of these properties a material can have a texture or a single input. My lighting shaders are physically based, so instead of specularity or shininess I use roughness and metallic as values to determine how reflective a material is.

SpriteBatch