1
$\begingroup$

I'm interested in how to organize in code (I prefer C++) lighting.
Problem is: I have Scene which contains Model where model contains Shader, someTextures and geometry Mesh. Now I want to add Light with the following fields:

struct Light
{
    Vector3f Color;
    float AmbientIntensity;
    Vector3f Direction;
    float DiffuseIntensity;
    float SpecularIntensity;
    Vector3f Position;
};

To apply light I need to know the values of this field and the position of the fragment pixel of geometry. This means I need to make a function like Light::lightModel(Model mdl) to get data from Model which I want to light. But also I want to make Light debuggable - show it in the scene like a Model (cube). How can I light all Models and do not light the light itself? Make two Scenes? Scene<Model> models and Scene<Light> lights and for loop for each like this?

for (const auto& light : lights->data()) {
    for (const auto& model : models->data())
    {
        light->lightModel(model);
        model->draw(camera);
    }
}
$\endgroup$
1
  • $\begingroup$ In deferred way you first loop through your models and render albedo, normals and positions to framebuffer color attachments and then apply all your lights in single draw call irrelevantly to number of models. $\endgroup$
    – mdkdy
    Commented Mar 28, 2017 at 11:03

1 Answer 1

1
$\begingroup$

If I understand you correctly then you are probably looking for a way in which lights in the scene interact with models in the scene. Also, you want each light to be visually debuggable in scene, maybe by drawing a cube. Here's one of the simplest way to do it. There could be more better & optimized ways of doing this.

You can have a class for Each light type eg> PointLight, DirectionalLight etc each with their own properties. You need to have a class which then keeps track of all the lights in the scene. This class will have list of light types in the scene. This class will also have functions for adding active lights from the scene to it's list of lights. Usual get-set functions for accessing individual lights will be required too.

class LightsManager
{
// maybe create singleton object here..
public:
   void GatherPointLights(PointLight* light);
   PointLight GetPointLight(int id);

private:
   int numPointLights;
   std::vector<PointLight*> vecPointLights; 
}

void LightsManager::GatherPointLights(PointLight* light)
{
    vecPointLights.push_back(light);
    numPointLights = vecPointLights.size();
}

In your class where you create objects in the scene, you can then add light objects from the scene to this LightManager using the function you created earlier.

Assuming scene class where all the objects including Lights are created...

void Scene::Init()
{
    // load mesh
    ...
    ...
    // add lights
    PointLight light1;
    light1.color = Color::Red;
    light1.position = vec3(0,0,0);
    LightManager::getInstance()->GatherPointLights(&light1);
}

If LightManager creates singleton object then you can then access all the lights in the scene by their type during actual rendering to extract their properties in a class where you render actual scene geometry by passing light color, position etc to a shader which draws scene geometry.

Now drawing the actual debug geometry for any light object, say cube for point light, I would make sure my PointLight type object has a way of rendering cube at a Point light position, using it's color property to draw cube of that same color with a flat color shader.

As per making sure lights are not lighting actual light debug geometry, if your cube drawing shader is a flat color shader representing color of a light, then it will not be affected by any light in the scene.

Hope this is what you asked for.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.