Search code examples
c++arraysopengldirectxgame-engine

Appopriate Container that acts like normal static array?


I am struggling with finding a correct and fast way to implement a dynamic light in game engine but having some issues (I hope my explanation is good enough as I amn't English native).

The Problem:

I need a way to store array of vectors (each have 4 floats) on stack so compiler could identify its size by sizeof operator and I can access the data easily, the easiest way to do this is:

PointLight pointLights[NR_POINT_LIGHTS];

but I want to add lights at so NR_POINT_LIGHTS will likely increase as I add more lights but of course NR_POINT_LIGHTS must be static const (I guess) I have a function like that:

class LightSystem{
 void BakeMyLights()
 {
   struct 
   {
      //PointLight pointLights[nooflights];//Sorry not possible since nooflights isn't const

      //PointLight pointLights[(const int)nooflights]; //Also fails as nooflights isn't a real constant "you can change it with func parameter

      //std::anycontainer<PointLight> pointLights; // Sizeof operator gives size of the internal pointer which isn't required also it is required to be on stack

    }ubo;

    MyLovely_OpenGL_And_DirectX_UBO.Update(&ubo,sizeof(ubo));
 }
    private:
    int nooflights;
};

What I have been using for a while (the old code which I want to replace)...

    struct SHADERUBO_t {

    // 4 float = 4x4 = 16 byte
    Math::Vector4 camPosandMaterialshininess;

    // 3 vector4 = 3x16 = 48 byte
    _PointLight pointLights[4];

}ShaderUBO; //16 + 48 = 64


MyLovely_OpenGL_And_DirectX_UBO.Update(&ShaderUBO,sizeof(ShaderUBO));
//                                      ^^^^^^^^^ , ^^>>> Gets correct Size 64
// ShaderUBO allocated on stack so Opengl access its data correctly

The Question

Is there a right way to implement it so that every time I "Bake" the system I can create a struct with static arrays that is stored on stack and keep it alive ???

Also, All of the code shown above is pseudo code , and it's not the actual implementation.

Thanks.


Solution

  • It is not possible to have an object that can change it's size but returns the correct size through sizeof. The sizeof operator is evaluated at compile time and can thus only return sizes that are available at this point. Since a dynamic size is only known at runtime it is impossible to do what you want.

    Besides the problems on the C++ side (which could be worked around by uploading the data in two steps, first the matrix and then the pointlight data with correct offset), a UBO in OpenGL can only contain Arrays with a constant length. Arrays of undetermined length are only available for SSBO. Due to this, you always have to supply data for the whole shader array. If you want to change the number of lights, you have to recompile the shader.