?
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?