I am having problems with specular shaders and lighting in general.
Here's the executable so you know what I'm talking about (Download zip, extract, run YFNH.jar): https://github.com/fiendfan1/YFNH-LWJGL/tree/master/3DYFNH/YFNH%20Executable (https://github.com/fiendfan1/YFNH-LWJGL/tree/master/3DYFNH/YFNH%20Executable)
First of all, All I call is
glLight(id, GL_POSITION, lightPosition);
glLightModel(GL_LIGHT_MODEL_AMBIENT, ambientInt);
glLight(id, GL_AMBIENT, ambientInt);
glLight(id, GL_SPECULAR, specInt);
glLight(id, GL_DIFFUSE, diffInt);
to set up the light, but it always follows the camera.
I added some code that just changes the lightPosition FloatBuffer and then updates the light.
I call this code when a certain key is pressed (Q), and it basically makes it look like the highlighted parts are "painted" on. They don't move with movement of the camera.
To update the camera's position I am using:
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_MODELVIEW);
glRotatef(this.parent.rotation.x, 1, 0, 0);
glRotatef(this.parent.rotation.y, 0, 1, 0);
glRotatef(this.parent.rotation.z, 0, 0, 1);
glTranslatef(-this.parent.position.x, -this.parent.position.y, -this.parent.position.z);
glPopAttrib();
The shaders Are:
Vert:
#version 120
varying vec4 varyingColour;
varying vec3 varyingNormal;
varying vec4 varyingVertex;
varying int texID;
attribute int textureID;
void main()
{
texID = textureID;
// Pass the vertex colour attribute to the fragment shader.
varyingColour = gl_Color;
// Pass the vertex normal attribute to the fragment shader.
varyingNormal = gl_Normal;
// Pass the vertex position attribute to the fragment shader.
varyingVertex = gl_Vertex;
//Set gl_Position
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
//Set texture coords
gl_TexCoord[0] = gl_MultiTexCoord0;
}
Frag:
#version 120
uniform sampler2D[10] textures;
varying vec4 varyingColour;
varying vec3 varyingNormal;
varying vec4 varyingVertex;
varying int texID;
void main()
{
//Position of vertex in modelview space
vec3 vertexPosition = (gl_ModelViewMatrix * varyingVertex).xyz;
//Surface normal of current vertex
vec3 surfaceNormal = normalize((gl_NormalMatrix * varyingNormal).xyz);
//Direction light has traveled to get to vertexPosition
vec3 lightDirection = normalize(gl_LightSource[0].position.xyz - vertexPosition);
//Basically how much light is hitting the vertex
float diffuseLightIntensity = max(0.0, dot(surfaceNormal, lightDirection));
//"Main color" of vertex
vec3 diffColor = diffuseLightIntensity * varyingColour.rgb;
//Lowest light level possible
vec3 ambColor = gl_LightModel.ambient;
//Direction light is reflected off of surface normal
vec3 reflectionDirection = normalize(reflect(-lightDirection, surfaceNormal));
//The intensity of reflection (specular)
float specular = max(0.0, dot(surfaceNormal, reflectionDirection));
//Instantiate specColor for scope
vec3 specColor = vec3(0.0, 0.0, 0.0);
if (diffuseLightIntensity != 0.0)
{
//Raise specular to exponent of shininess
float fspecular = pow(specular, gl_FrontMaterial.shininess);
specColor = fspecular;
}
if(texID == -1)
{
//Does not have a texture, just use diffuse, specular, and ambient colors
gl_FragColor = vec4(ambColor, 1.0) + vec4(diffColor + specColor, 1.0);
}
else
{
//Fragment has texture, use the texture's color, and diffuse, specular, and ambient colors
gl_FragColor = vec4(ambColor, 1.0) + vec4(diffColor * vec3(texture(textures[texID], gl_TexCoord[0].st)) + specColor, 1.0);
}
}
From OpenGL FAQs:
Quote
A light's position is transformed by the current ModelView matrix at the time the position is specified with a call to glLight*(). This is analogous to how geometric vertices are transformed by the current ModelView matrix when they are specified with a call to glVertex*()
Perhaps this is your problem?
Also, you don't need the varyingVertex attribute in your shaders. You can access a fragments position with gl_FragCoord (vec4)