Creating spotlights for lighting a stage


I am working on a project that reads DMX signal (used for controlling lights in bars, clubs, theatres) sent over USB and displays it in a 3D scene.

I am new to Monogame and XNA development, but I’ve managed to find my way around to create the basic project, render a stage object and stagelight objects.

I am not exactly sure how to create lights for each stage light though. I have had a look at creating a custom shader with point lights, but haven’t really been successful.

I am wondering if someone could point me in the right direction of how to approach this problem.

Do you have any previous shader experience?

Spotlights can be treated like pointlights, except they also have a direction and spotlight angle.

Then when calculating the light you get the direction from light to pixel (as always) and compare it with the spotlight direction.
For example a simple dot product will do. If the value is above a certain threshold (defined by your angle, or the cosine of the angle for dot products) you light the pixel.

here is an example snippet from such a shader

float DdotLD = saturate(dot(-DirectionToLight, normalize(SpotLightDirection[i])));

                float coneAngle = SpotLightAngle[i];

                if (DdotLD > coneAngle)
                    DdotLD = 1 - mad(DdotLD, 2, -coneAngle * 2); //-1.8f); //(DdotLD - 0.9) * 2;

                    DdotLD *= DdotLD;

                    float NdotLPoint = saturate(dot(DirectionToLight, normal));

                    diffusePoint += (1 - DdotLD) * NdotLPoint * SpotLightIntensity[i] * attenuation * SpotLightColor[i];
                    if (SpecularPointLights)
                        specularPoint += SpecularCookTorrance(NdotLPoint, normal, DirectionToLight, CameraDir, SpotLightIntensity[i], SpotLightColor[i], roughness, f0) * attenuation * (1 - DdotLD);

I have some basic knowledge about shading from a Graphics course I took at Uni a couple of months ago, but that covered only the theoretical parts and therefore I have no experience with actually implementing it.

I have tried using this shader to add some point lights to my scene, but the object is just black when drawn if I use this compared to using the default BasicEffect and mesh.Draw().

Upon further inspection, I have realised this might have something to do my 3d model, mostly because when it is loaded its ((BasicEffect)(mesh.Effect[0])).Texture is null and therefore it’s not passing any DiffuseTexture to the shader. I’ve tried passing in a random texture to the shader, and I’ve managed to get ambient lighting to work, but I can’t see any point lighting.

The best way to debug a shader is to return intermediate results instead of the final color, and see if those make sense.

For example you will need correct normals for a point light shader. So right after the normal vector is calculated/sampled in the pixel shader add a

return float4(normal, 0);

Your object should now be colored according to the direction of normals on the surface. If it’s not, you know something is wrong with your normals.

Then you could check if the distance/distanceSqr from the light source is correct. If your object is about 10 meters away from the light source, distanceSqr should be around 100. So add a

return distanceSqr / 200;

and you should get roughly 0.5, that translates to a mid-gray object. Usually you want to map results to a 0 to 1 range.