Search code examples
c#openglglslopentk

Is there any way to use complex/derived classes in GLSL?


In my OpenGL projects I've never used custom structs in my GLSL shaders. Until now I was perfectly fine with arrays of mat4,vec4,int. In my latest project, I'm considering adding support for a multiple light system. Again whenever required, I simply used separate arrays for light positions, colors and so on. This is obviously not convenient but considering the scale of my past applications this was sufficient.

In my latest project though I think I'll have to organize my data a bit more because arrays are absolutely not that manageable but also not that expendable as well. So to the point, I know that GLSL supports structs, but the problem is that in my main code I have way more "complicated" classes with data that I don't need in the GLSL shader. For example this is my main light class which is actually derived from a very basic model class:

public class Model
{
    public string name;
    public Vector3 position;
    public Matrix4 rotationMatrix;
    //Many more attributes and properties related to the GUI
}


public class Light: Model
{
    public Vector3 color;
    public Vector3 ambient;
    public float intensity;
    public float specular;
}

Given this data structure, I have absolutely no clue how to use this directly into GLSL shaders. So my solution for now is to provide a simplified version of the class as a struct, which contain just the necessary information that I need in the shaders. This doesn't sound a good solution, because I'll have to practically maintain 2 versions for all of my different model classes.

public struct SimpleLightStruct
{
    public Vector4 position;
    public Vector3 color;
    public Vector3 ambient;
    public float intensity;
    public float specular;
}

So my question is, is this solution the only option? How do more advanced game developers organize their data?

Since I'm using the GUI in order to modify object properties, I have to somehow add Properties to pretty much all of my data classes and this takes away all the simplicity of the classes, I can't obviously account for class sizes for OpenGL callbacks, but even if I didn't have the extra properties, even the name field prohibits me from using a common struct for both uses.


Solution

  • C (and therefore OpenGL) does not speak C#. It only speaks the very small subset of C#. So when interacting with a C API, that's what you have to stick to.

    You are marshaling data from C# to a C API, so you have to follow the rules for doing so. That typically means that, if you want to just copy some object directly into the C API's memory, you need to stick with only the C# struct types that have C analogs.

    How exactly you do that is up to you. You could store your data in C# however you want, and then copy it to a temporary object for forwarding into an OpenGL buffer object. Or you could store an array of C structs, which is parallel to the C# light data, with your C# data having the index of the C struct it matches. Or other things.