OpenGL/OpenTK Shader, keine Belichtung



  • Hi,
    ich folge dem Code zu Diffuse-Lighting mit GLSL aus der OpenGL Superbible 5. Den Code übertrage ich nach C#, doch irgendwo ist ein kleiner Fehler. Die Normalenvektoren werden nicht korrekt an den Vertexshader übergeben. Bzw sieht es so aus, als wären die vNormal-Attributes immer der Nullvektor.

    Hier was fehlerhaft gerendert wird, alles schwarz:
    http://prntscr.com/4sm8rr

    Hier der Code des Vertexshaders:

    // Simple Diffuse lighting Shader
    // Vertex Shader
    // Richard S. Wright Jr.
    // OpenGL SuperBible
    #version 130
    
    // Incoming per vertex... position and normal
    in vec4 vVertex;
    in vec3 vNormal;
    
    // Set per batch
    uniform vec4	diffuseColor;	
    uniform vec3	vLightPosition;
    uniform mat4	mvpMatrix;
    uniform mat4	mvMatrix;
    uniform mat3	normalMatrix;
    
    // Color to fragment program
    smooth out vec4 vVaryingColor;
    
    void main(void) 
        { 
    
    	//vNormal ist null
    
        // Get surface normal in eye coordinates
    
        vec3 vEyeNormal = normalMatrix * vNormal; // vec3(vVertex);
    
        // Get vertex position in eye coordinates
        vec4 vPosition4 = mvMatrix * vVertex;
        vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
    
        // Get vector to light source
        vec3 vLightDir = normalize(vLightPosition - vPosition3);
    
        // Dot product gives us diffuse intensity
        float diff = max(0.0, dot(vEyeNormal, vLightDir));
    
        // Multiply intensity by diffuse color
        vVaryingColor.rgb =  diff * diffuseColor.rgb;
        vVaryingColor.a = diffuseColor.a;
    
        // Let's not forget to transform the geometry
        gl_Position = mvpMatrix * vVertex;
        }
    

    Der Fragmentshader macht nur dies:

    // Simple Diffuse lighting Shader
    // Fragment Shader
    // Richard S. Wright Jr.
    // OpenGL SuperBible
    #version 330
    
    out vec4 vFragColor;
    smooth in vec4 vVaryingColor;
    
    void main(void)
       { 
       vFragColor = vVaryingColor;
       }
    

    Wenn ich im Vertexshader testweise statt

    vec3 vEyeNormal = normalMatrix * vNormal;
    

    schreibe

    vec3 vEyeNormal = normalMatrix * vec3(vVertex);
    

    wird eine Beleuchtung gerendert. Z.b. bei einer Einheitskugel entsprechen die Normalenvektoren ja gerade den Vertices. Daraus schließe ich mal, dass die Matrizen korrekt übergeben werden als Uniforms.

    Nun denn, hier der restliche Code:

    Setup:

    diffuseLightShader = Shader.Load(
                    Path.Combine(baseFolder, "vertexshader.glsl"),
                    Path.Combine(baseFolder, "fragmentshader.glsl")
                    , new Tuple<Shader.ShaderAttribute, string>(Shader.ShaderAttribute.Vertex, "vVertex")
                    , new Tuple<Shader.ShaderAttribute, string>(Shader.ShaderAttribute.Normal, "vNormal")
                    );
    
                locColor = GL.GetUniformLocation(diffuseLightShader, "diffuseColor");
                locLight = GL.GetUniformLocation(diffuseLightShader, "vLightPosition");
                locMVP = GL.GetUniformLocation(diffuseLightShader, "mvpMatrix");
                locMV = GL.GetUniformLocation(diffuseLightShader, "mvMatrix");
                locNM = GL.GetUniformLocation(diffuseLightShader, "normalMatrix");
    

    Shader laden:

    public enum ShaderAttribute
            {
                Vertex = 0, Color, Normal, Tex0, Tex1, Tex2, Tex3, Last
            }
    
            public static int Load(string vertexFilePath, string fragmentFilePath, params Tuple<ShaderAttribute, string>[] Attribs)
            {
                int VertexShaderID = GL.CreateShader(ShaderType.VertexShader);
                int FragmentShaderID = GL.CreateShader(ShaderType.FragmentShader);
    
                string VSCode = File.ReadAllText(vertexFilePath);
                string FSCode = File.ReadAllText(fragmentFilePath);
    
                GL.ShaderSource(VertexShaderID, VSCode);
                GL.CompileShader(VertexShaderID);
    
                int result;
                GL.GetShader(VertexShaderID, ShaderParameter.CompileStatus, out result);
                Console.WriteLine(GL.GetShaderInfoLog(VertexShaderID));
    
                GL.ShaderSource(FragmentShaderID, FSCode);
                GL.CompileShader(FragmentShaderID);
    
                Console.WriteLine(GL.GetShaderInfoLog(FragmentShaderID));
    
                int program = GL.CreateProgram();
                GL.AttachShader(program, VertexShaderID);
                GL.AttachShader(program, FragmentShaderID);
    
                foreach (var tuple in Attribs)
                {
                    GL.BindAttribLocation(program, (int)tuple.Item1, tuple.Item2);
                }
    
                GL.LinkProgram(program);
    
                Console.WriteLine(GL.GetProgramInfoLog(program));
    
                GL.DeleteShader(VertexShaderID);
                GL.DeleteShader(FragmentShaderID);
    
                Console.WriteLine("--------");
    
                return program;
            }
    

    Rendering:

    protected override void OnRenderFrame(FrameEventArgs e)
            {
                NonRenderingWorkloadOnRenderFrame();
                base.OnRenderFrame(e);
    
                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    
                Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
                Matrix4 view = Camera.GetCameraMatrix();
                Matrix4 model = frame1.GetMatrix();
    
                Matrix4 MV = model*view;
    
                Matrix4 MVP = MV * projection;
    
                GL.UseProgram(diffuseLightShader);
    
                GL.EnableClientState(ArrayCap.VertexArray);
                GL.EnableClientState(ArrayCap.NormalArray);
    
                Vector3 eyeLight = new Vector3(0, 10, 0);
                Vector4 diffuseColor = new Vector4(0, 0, 1, 0);
    
                GL.Uniform4(locColor, ref diffuseColor);
                GL.Uniform3(locLight, ref eyeLight);
                GL.UniformMatrix4(locMVP, false, ref MVP);
                GL.UniformMatrix4(locMV, false, ref MV);
    
                float[] normal = new float[9];
                Matrix4Dto3F(MV, ref normal, false);
    
                GL.UniformMatrix3(locNM, 1, false, normal);
    
                sphere1.Draw();
    
                GL.DisableClientState(ArrayCap.NormalArray);
                GL.DisableClientState(ArrayCap.VertexArray);
    
                SwapBuffers();
    }
    

    Sieht jemand einen Fehler?


Anmelden zum Antworten