Search code examples
c#openglopengl-escameraopentk

C# OpenGL - Trying to get the light to move with the camera using shaders


I am currently building a test scene with shaders. Here is my Vertext Shader code:

public const string VertexShaderText = @"
    #version 130

    in vec3 vertexPosition;
    in vec3 vertexNormal;
    in vec3 vertexTangent;
    in vec2 vertexUV;

    uniform vec3 light_direction;

    out vec3 normal;
    out vec2 uv;
    out vec3 light;

    uniform mat4 projection_matrix;
    uniform mat4 view_matrix;
    uniform mat4 model_matrix;
    uniform bool enable_mapping;

    void main(void)
    {

        normal = normalize((model_matrix * vec4(floor(vertexNormal), 0)).xyz);
        uv = vertexUV;

        mat3 tbnMatrix = mat3(vertexTangent, cross(vertexTangent, normal), normal);
        light = (enable_mapping ? light_direction * tbnMatrix : light_direction);

        gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1);

    }
    ";

Here is my Fragment Shader:

public const string FragmentShaderText = @"
    #version 130

    uniform sampler2D colorTexture;
    uniform sampler2D normalTexture;

    uniform bool enableToggleLighting;
    uniform mat4 model_matrix;
    uniform bool enable_mapping;
    uniform float alpha;
    uniform float ambi;

    in vec3 normal;
    in vec2 uv;
    in vec3 light;

    out vec4 fragment;

    void main(void)
    {   

        vec3 fragmentNormal = texture2D(normalTexture, uv).xyz * 2 - 1;
        vec3 selectedNormal = (enable_mapping ? fragmentNormal : normal);
        float diffuse = max(dot(selectedNormal, light), 0);
        float ambient = ambi;
        float lighting = (enableToggleLighting ? max(diffuse, ambient) : 1);

        fragment = vec4(lighting * texture2D(colorTexture, uv).xyz, alpha);
    }
    ";

My Project is initialized like this:

CanvasControlSettings.ShaderProgram.Use();
        CanvasControlSettings.ShaderProgram["projection_matrix"].SetValue(mainSceneProj);
        CanvasControlSettings.ShaderProgram["light_direction"].SetValue(new Vector3(0f, 0f, 1f));
        CanvasControlSettings.ShaderProgram["enableToggleLighting"].SetValue(CanvasControlSettings.ToggleLighting);
        CanvasControlSettings.ShaderProgram["normalTexture"].SetValue(1);
        CanvasControlSettings.ShaderProgram["enable_mapping"].SetValue(CanvasControlSettings.ToggleNormalMapping);

My rotation moves the camera around the object. I want to move the light position along with the camera so that the shading is always visible.

How can I send the Camera Pos to the shader and implement this ?

From the front: front

Rotated:

rotated

EDIT:

I Updated the Camera Position after rotate like this:

GL.Light(LightName.Light0, LightParameter.Position, new float[] { CanvasControlSettings.Camera.Position.X, CanvasControlSettings.Camera.Position.Y, CanvasControlSettings.Camera.Position.Z, 0.0f } );

And changed the light line to this

light = gl_LightSource[0].position.xyz;

This almost works perfectly accept that the material light color is now way to bright! I would show pictures but it seems I need more rep.

EDIT:

Ok, after following provided links, I found my way. I changed the Vertex Shader light code to:

 vec4 lightPos4 = vec4(gl_LightSource[0].position.xyz, 1.0);
        vec4 pos4 = model_matrix * vec4(vertexPosition, 1.0);
        light = normalize((lightPos4 - pos4).xyz);

Works perfectly now. Thanks


Solution

  • You don't need to send the camera position to your shader. Just change your lights position to the camera position and send your light to your shader.