I know it's stupid.. not used namespaces in C++ before.. off I go searching..
Well that seems simple enough, sweet!
My loader now just holds an instance of an nVectorMath, now renamed VectorMagic lol
So if I'm generating these normals correctly, and I'm confident I'm putting them on the GPU correctly, and I've got one directional white light, and I set the colour of whatever is being shaded to bright green, what's the most likely cause of my completely black mesh?
Heres what happens / what I know for phong shading
- vertex position and vertex normal are sent to the vertex shader
- here they are transformed to world space and sent to the fragment shader
- in the fragment shader work out all the lighting razzmataz
- blend specular and diffuse colours, sum them, and output the final colour
So here we go, theres a lot of code here, which does the process above and gives me a black mesh..
Get the Inverse Transpose Model Matrix
glm::mat4 GLModel::GetInvTransModelMatrix()
{
return glm::transpose( glm::inverse( modelMatrix ) );
}
... Everything gets put into the pipleline..
glm::vec4 cPos = glm::vec4( mainCam->GetPosition(), 1.0 );
glm::vec4 slDir( 0.0f, 1.0f, 0.0f, 0.0f );
glm::vec4 slDif( 1.0f, 1.0f, 1.0f, 1.0f );
glm::vec4 slSpe( 0.07f, 0.8f, 0.9f, 1.0f );
// cam, direction, diffuse, specular, falloff/attenuation, inverse transpose model matrix
theBeast->m_Shader.SetLightUniforms( cPos, slDir, slDif, slSpe, 0.8f, theBeast->GetInvTransModelMatrix() );
// world mx, view mx, proj mx, scale, viewmode
theBeast->Render( glm::mat4(1.0), mainCam->GetViewMatrix(), m_ogl->GetProjectionMatrix(), 0.07f, GetViewMode() ); // for wireframe and what not. Using fill mode atm
then in the vertex shader..
#version 330
uniform mat4 worldMx;
uniform mat4 viewMx;
uniform mat4 projMx;
uniform mat4 modelMatrix;
uniform mat4 invtrans_modelMatrix;
uniform float scale_xyz;
layout (location=0) in vec4 vertexPos;
layout (location=1) in vec3 vertexNormal;
out vec3 colour;
out vec3 normalWorld;
out vec4 positWorld;
void main(void)
{
vec4 v = vertexPos;
v.x *= scale_xyz;
v.y *= scale_xyz;
v.z *= scale_xyz;
//-----------------------------------------------
colour = vec3( 0.3, 0.4, 0.7 ); // pale blue
// vertex position in world coordinate space - for fragment shader
positWorld = modelMatrix * v;
// normal transformed to world coordinate space - again for fragment shader
normalWorld = ( invtrans_modelMatrix * vec4(vertexNormal, 0.0) ).xyz;
gl_Position = projMx * viewMx * worldMx * modelMatrix * v;
}
And finally the Pixel shader..
#version 330
uniform vec4 cameraPos;
uniform vec4 lightDirection;
uniform vec4 lightDiffuse;
uniform vec4 lightSpecular;
uniform float lightFalloff;
in vec3 colour;
in vec3 normalWorld;
in vec4 positWorld;
layout (location=0) out vec4 fragColour;
void main(void)
{
// make sure light direction vector is unit length (store in L)
vec4 L = normalize( lightDirection );
// important to normalise length of normal otherwise shading artefacts occur
vec3 N = normalize( normalWorld );
// calculate lambertian term
float lambertian = clamp( dot( L.xyz, N ), 0.0, 1.0 );
//
// calculate diffuse light colour
//
vec3 diffuseColour = colour.rgb * lightDiffuse.rgb * lambertian; // input colour actually diffuse colour
//
// calculate specular light colour
//
// vector from point on object surface in world coords to camera
vec3 E = cameraPos.xyz - positWorld.xyz;
E = normalize(E);
// reflected light vector about normal N
vec3 R = reflect(-L.xyz, N);
float specularIntensity = pow( max( dot(R, E), 0.0 ), lightFalloff );
vec3 specularColour = vec3(1.0f, 1.0f, 1.0f) * lightSpecular.rgb * specularIntensity * lambertian;
//
// combine colour components to get final pixel / fragment colour
//
vec3 rgbColour = diffuseColour + specularColour;
// output final colour to framebuffer
fragColour = vec4( rgbColour, 1.0 );
// fragColour = vec4( colour, 1.0 );
}