fireshadow4126's picture

Question on shaders

Hello. I'm working on an 3d gaming application, and I'm trying to use per-pixel lighting. However, when I run what I have, the application closes before showing anything and my log file shows SHADER_COMPILATION_ERROR. My vertex and fragment shaders are exactly the ones from Beginning OpenGL Game Programming 2nd Edition by Luke Benstead with Dave Astle and Kevin Hawkings. Here they are:

Vertex:

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
uniform mat3 normal_matrix;
 
uniform vec4 material_ambient;
uniform vec4 material_diffuse;
uniform vec4 material_specular;
uniform vec4 material_emissive;
uniform float material_shininess;
 
struct light {
	vec4 position;
	vec4 diffuse;
	vec4 specular;
	vec4 ambient;
 
	float constant_attenuation;
	float linear_attenuation;
	float quadratic_attenuation;
}
 
uniform light light0;
 
in vec3 a_Vertex;
in vec2 a_TexCoord0;
in vec3 a_Normal;
 
out vec2 texCoord0;
out vec3 normal;
out vec3 lightDir;
out vec3 halfVector;
 
out vec4 vertDiffuse;
out vec4 vertAmbient;
out float dist;
 
void main(void)
{
	normal = normalize(normal_matrix * a_Normal);
	vec4 pos = modelview_matrix * vec4(a_Vertex, 1.0);
 
	vec3 lightPos = (modelview_matrix * light0.position).xyz;
	lightDir = lightPos - pos.xyz;
	vec3 E = -(pos.xyz);
 
	dist = length(lightDir);
	lightDir = normalize(lightDir);
 
	halfVector = normalize(lightPos + E);
 
	vertDiffuse = material_diffuse * light0.diffuse;
	vertAmbient = material_ambient * light0.ambient;
	texCoord0 = a_TexCoord0;
 
	gl_Position = projection_matrix * pos;
}

Fragment:

uniform sampler2D texture0;
 
uniform vec4 material_ambient;
uniform vec4 material_diffuse;
uniform vec4 material_specular;
uniform vec4 material_emissive;
uniform float material_shininess;
 
struct light {
	vec4 position;
	vec4 diffuse;
	vec4 specular;
	vec4 ambient;
 
	float constant_attenuation;
	float linear_attenuation;
	float quadratic_attenuation;
};
 
uniform light light0;
 
in vec2 texCoord0;
in vec3 normal;
in vec3 lightDir;
in vec3 halfVector;
 
in vec4 vertDiffuse;
in vec4 vertAmbient;
in float dist;
 
out vec4 outColor;
 
void main(void) {
	vec3 N = normalize(normal);
 
	float NdotL = max(dot(N, normalize(lightDir)), 0.0);
 
	vec4 color = vec4(0.0);
 
	if (NdotL > 0.0)
	{
		color += vertDiffuse * NdotL;
 
		vec3 HV = normalize(halfVector);
		float NdotHV = max(dot(N, HV), 0.0);
		color += material_specular * light0.specular * pow(NdotHV, material_shininess);
	}
 
	float attenuation = 1.0 / (light0.constant_attenuation +
					light0.linear_attenuation * dist +
					light0.quadratic_attenuation * dist * dist);
 
	outColor = ((color * attenuation) + vertAmbient) * texture(texture0, texCoord0.st);
}

Relevant parts of my GLSLProgram class:

public sealed class GLSLProgram
    {
        struct GLSLShader
        {
            public int id;
            public string filename;
            public string source;
        }
 
        private GLSLShader vertex_Shader;
        private GLSLShader fragment_Shader;
        private Dictionary<string, int> uniformMap;
        private Dictionary<string, int> attribMap;
        private int programID;
 
        public GLSLProgram(string vertShaderFile, string fragShaderFile)
        {
            vertex_Shader = new GLSLShader();
            fragment_Shader = new GLSLShader();
            uniformMap = new Dictionary<string, int>();
            attribMap = new Dictionary<string, int>();
            vertex_Shader.filename = vertShaderFile;
            fragment_Shader.filename = fragShaderFile;
            readShaderSources();
        }
 
        public bool Init()
        {
            Thread.Sleep(1);
            programID = GL.CreateProgram();
            vertex_Shader.id = GL.CreateShader(ShaderType.VertexShader);
            fragment_Shader.id = GL.CreateShader(ShaderType.FragmentShader);
            if (!(vertex_Shader.filename.Equals("INTERNAL")) && !(fragment_Shader.filename.Equals("INTERNAL")))
            {
                readShaderSources(); 
            }
            if (vertex_Shader.source.Equals(String.Empty) || fragment_Shader.source.Equals(String.Empty))
            {
                SurviveErrors.SetErrorFlag("SHADER_SOURCE_NONEXISTANT_ERROR");
                return false;
            }
            GL.ShaderSource(vertex_Shader.id, vertex_Shader.source);
            GL.ShaderSource(fragment_Shader.id, fragment_Shader.source);
            if (!compileShader(vertex_Shader) || !compileShader(fragment_Shader))
            {
                SurviveErrors.SetErrorFlag("SHADER_COMPILATION_ERROR");
                return false;
            }
            GL.AttachShader(programID, vertex_Shader.id);
            GL.AttachShader(programID, fragment_Shader.id);
            GL.LinkProgram(programID);
            return true;
        }
 
        public void Unload()
        {
            GL.DetachShader(programID, vertex_Shader.id);
            GL.DetachShader(programID, fragment_Shader.id);
            GL.DeleteShader(vertex_Shader.id);
            GL.DeleteShader(fragment_Shader.id);
            GL.DeleteProgram(programID);
        }
 
        private bool compileShader(GLSLShader shader)
        {
            GL.CompileShader(shader.id);
            int result = 12047375;
            GL.GetShader(shader.id, ShaderParameter.CompileStatus, out result);
 
            if (result == 0)
            {
                Console.Error.WriteLine("Your shader has errors.  Please validate.");
                return false;
            }
            return true;
        }
 
        private void readShaderSources()
        {
            using (TextReader reader = File.OpenText(vertex_Shader.filename))
            {
                while (reader.Peek() > -1)
                {
                    vertex_Shader.source += reader.ReadLine();
                }
            }
            using (TextReader reader = File.OpenText(fragment_Shader.filename))
            {
                while (reader.Peek() > -1)
                {
                    fragment_Shader.source += reader.ReadLine();
                }
            }
        }
 
        public void BindShader()
        {
            GL.UseProgram(programID);
        }
    }

I'm on Windows XP 32-bit Professional. I have an Intel I7 Core Duo and an NVIDIA GeForce 210.

Please help! Thanks in advance.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Check what GL.GetShaderInfoLog(shader.id) returns when the shader fails to compile. It should point to the exact location of the error (line number and error type).

fireshadow4126's picture

ouch. I did that for just the vertex shader to try it and it returned this:

0(1) : warning C7537: OpenGL does not allow 'uniform' after a type specifier
0(1) : error C1002: the name "light" is already defined at 0(1)
0(1) : error C0000: syntax error, unexpected identifier, expecting ',' or ';' at token "light0"
0(1) : error C0501: type name expected at token "light0"
0(1) : error C5060: out can't be used with non-varying texCoord0
0(1) : error C5060: out can't be used with non-varying normal
0(1) : error C5060: out can't be used with non-varying lightDir
0(1) : error C5060: out can't be used with non-varying halfVector
0(1) : error C5060: out can't be used with non-varying vertDiffuse
0(1) : error C5060: out can't be used with non-varying vertAmbient
0(1) : error C5060: out can't be used with non-varying dist
0(1) : error C1038: declaration of "projection_matrix" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "modelview_matrix" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "normal_matrix" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "material_ambient" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "material_diffuse" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "material_specular" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "material_emissive" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "material_shininess" conflicts with previous declaration at 0(1)
0(1) : warning C7537: OpenGL does not allow 'uniform' after a type specifier
0(1) : error C1002: the name "light" is already defined at 0(1)
0(1) : error C0000: syntax error, unexpected identifier, expecting ',' or ';' at token "light0"
0(1) : error C0501: type name expected at token "light0"
0(1) : error C1038: declaration of "light0" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "a_Vertex" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "a_TexCoord0" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "a_Normal" conflicts with previous declaration at 0(1)
0(1) : error C1038: declaration of "texCoord0" conflicts with previous declaration at 0(1)
0(1) : error C5060: out can't be used with non-varying texCoord0
0(1) : error C1038: declaration of "normal" conflicts with previous declaration at 0(1)
0(1) : error C5060: out can't be used with non-varying normal
0(1) : error C1038: declaration of "lightDir" conflicts with previous declaration at 0(1)
0(1) : error C5060: out can't be used with non-varying lightDir
0(1) : error C1038: declaration of "halfVector" conflicts with previous declaration at 0(1)
0(1) : error C5060: out can't be used with non-varying halfVector
0(1) : error C1038: declaration of "vertDiffuse" conflicts with previous declaration at 0(1)
0(1) : error C5060: out can't be used with non-varying vertDiffuse
0(1) : error C1038: declaration of "vertAmbient" conflicts with previous declaration at 0(1)
0(1) : error C5060: out can't be used with non-varying vertAmbient
0(1) : error C1038: declaration of "dist" conflicts with previous declaration at 0(1)
0(1) : error C5060: out can't be used with non-varying dist
0(1) : error C1013: function "main" is already defined at 0(1)

What is this?!

the Fiddler's picture

Now that's a good question...

I have a feeling that readShaderSources() truncates line endings, confusing the compiler. Try this, instead:

private void readShaderSources()
{
    vertex_Shader.source = File.ReadAllText(vertex_Shader.filename);
    fragment_Shader.source = File.ReadAllText(fragment_Shader.filename);
}
fireshadow4126's picture

ReadAllText() seemed to help a little bit. Note that I also changed my code to get errors from both the vertex shader and the fragment shader. What's weird is that the fragment shader produces no errors, and it didn't even before I used ReadAllText(). Anyway, the log file now becomes:

VERTSHADER_COMPILATION_ERROR
0(22) : warning C7537: OpenGL does not allow 'uniform' after a type specifier
0(22) : error C1002: the name "light" is already defined at 0(11)
0(22) : error C0000: syntax error, unexpected identifier, expecting ',' or ';' at token "light0"
0(22) : error C0501: type name expected at token "light0"
0(28) : error C5060: out can't be used with non-varying texCoord0
0(29) : error C5060: out can't be used with non-varying normal
0(30) : error C5060: out can't be used with non-varying lightDir
0(31) : error C5060: out can't be used with non-varying halfVector
0(33) : error C5060: out can't be used with non-varying vertDiffuse
0(34) : error C5060: out can't be used with non-varying vertAmbient
0(35) : error C5060: out can't be used with non-varying dist
the Fiddler's picture

You need to specify #version 130 (or higher) to use "in" and "out" specifiers. (Previous versions used "attribute" and "varying" instead.)

Moreover, your vertex shader seems to be missing a semicolon after the closing bracket of the light struct:

struct light {
    ...
};
fireshadow4126's picture

I just saw that before you posted. I added the #version 130 line to the top of both shaders and removed the light struct and replaced it with uniforms. The code doesn't produce any errors in the log file now, but when I run my code I see a window for a split second before it exits out. (Sigh)