giawa / opengl4csharp

OpenGL 4 Bindings (partially based on OpenTK) for C#
Other
232 stars 61 forks source link

GLSL Struct Support #12

Closed mbolt35 closed 7 years ago

mbolt35 commented 7 years ago

Update Shader parsing such that it's capable of handling custom glsl struct definitions. ProgramParams are now created for the inner struct locations.

Here's an example fragment shader that was failing:

#version 330 core

// Material definition
struct Material {
    vec3 color;
};

// Light definition
struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Light light;
uniform Material material;

in vec3 FragPosition;
in vec3 FragNormal;

out vec4 FragColor;

void main(void)
{
    vec3 lightDelta = light.position - FragPosition;

    vec3 n = normalize(FragNormal);
    vec3 l = normalize(lightDelta);

    float cosTheta = clamp(dot(n, l), 0.0f, 1.0f);

    vec3 ambient = light.ambient;
    vec3 diffuse = light.diffuse * cosTheta;

    vec3 fragColor = (ambient + diffuse) * material.color;
    FragColor = vec4(fragColor, 1);
}

Before this change, ShaderProgram would throw an error trying to parse the types for each ProgramParam, specifically when looking at: uniform Light light (exception was "Unsupported Type").

The named location lookup would use the format <uniform name>.<inner_property>, so the attached pull request provides a little extra assistance in creating those additional ProgramParam instances by looking for the struct token, then collecting each inner struct property (name + type), then storing in a Dictionary using the struct type name as a key.

When processing the uniforms, we first check to see if our type is in the struct Dictionary, and if so, loop through each inner property and apply the . format for the location lookups.

For instance, using the fragment shader above, the following would set the appropriate values in C#:

    _shader["light.position"].SetValue(_lightPosition);
    _shader["light.ambient"].SetValue(new Vector3(0.3f, 0.3f, 0.3f));
    _shader["light.diffuse"].SetValue(Vector3.One);
    _shader["light.specular"].SetValue(Vector3.One);

    // set the color to blue
    _shader["material.color"].SetValue(new Vector3(0.3, 0.3, 1.0));

There are a few things that I wasn't quite sure about:

I've been using your library for a C#/OpenGL live stream every week, and it's been an enormous help. Thank you for opening it up to the community. Hope this helps!

giawa commented 7 years ago

Awesome, thanks for the pull request! I'll try to find some time tomorrow to check this out. I'm glad you have found the library helpful.

giawa commented 7 years ago

As a completely random aside, the fact you are using this for voxel development is really awesome! I actually made a blog series about my own voxel engine using the same library here: https://www.giawa.com I look forward to checking out what you make

giawa commented 7 years ago

After thinking this over (and wondering why I went with parsing the GLSL back in the day) I decided to re-write this functionality by querying OpenGL directly for the uniform and attribute names. Since the OpenGL names are compatible with what you have done you should see no difference, and that way the code will now support future extensions to GLSL and any other parsing issues that we haven't foreseen.

Thanks again for submitting the pull request :D and hopefully you continue to find the library useful!

Commit that added this new functionality: 2050865d54e438cb6aa6597303809e55b7879e51

mbolt35 commented 7 years ago

Excellent! Thanks for the update!

When I was poking around for GL bindings, I came across your blog, and it made the decision very easy. We haven't made it that far into development since it's only a few hours 2-3 times a week. It's mainly been a linear algebra refresher (I'm still struggling to remember rotation transforms and quaternions, yikes), but we are getting into some of the data structures, terrain generation, etc... so hopefully it won't be much longer until we get into the core voxel stuff. I'm going to let viewers drive a lot of the "what we do" after we establish the basics. We'll see where that goes :)

Thanks again for dropping and line, and the library update!

mbolt35 commented 7 years ago

Oh, these are all unedit cuts, so they can be super lengthy. It's mostly me struggling, which can be somewhat entertaining: https://www.youtube.com/playlist?list=PLxLT4bny07yRB_kIDMYFeSpq2W7iNiDEu

giawa commented 7 years ago

Very cool! I'll definitely be checking it out! Let me know if you run into any pain points with the bindings, and I'll see what I can do to help out.