Hey everone. In my vertex shader, I reckon I’m not calculating the inverse() of a mat3 properly. I am trying to get the brick shader demo from the orange book to work and I’ve got it to render, but the lighting looks a little off. I would have used the built in inverse() that the book claims exists for >= 1.40 (table 5.5 of the Orange Book (p137)), but my nvidia driver complains it doesn’t have it:
warning C7547: extension GL_EXT_gpu_shader5 not supported in profile gp4vp
What is a shader profile anyways and how does one select one in the first place?
If I remove the #extension, I get…
error C7531: global function inverse requires "#extension GL_EXT_gpu_shader5 : enable" before use
Since inverse() doesn’t seem to be implemented, I’ve tried implementing it myself. The code for my vertex shader is as follows. I am confident the fragment shader is ok.
/*
Name: brick.glslv
Description: Vertex shader to procedurally generate brick texture on model...
*/
// We want at least GLSL 1.50...
#version 150
// We need this for inverse(), but I thought it was already supported in
// GLSL 1.40...
#extension GL_EXT_gpu_shader5 : enable
// Vertex attributes...
// Vertex position in model coordinates...
in vec4 mcVertex;
// Normal plane / vector in model coordinates. Assume already normalized...
in vec3 mcNormal;
// Uniform variables...
// Transformation matrices...
uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;
// Light position in eye coordinates...
uniform vec3 ecLightPosition;
// Constants...
// Lighting parameters...
const float SpecularContribution = 0.3;
const float DiffuseContribution = 1.0 - SpecularContribution;
// Outputs to be interpolated for the fragment shader...
// Intensity of light at this vertex...
out float LightIntensity;
// Position of vertex to be interpolated in model coordinates...
out vec2 mcPosition;
// Calculate inverse, in case built-in not supported...
mat3 inverse(const in mat3 Matrix)
{
// Calculate the determinant...
float D = determinant(Matrix);
// Singular matrix, problem...
if(D == 0.0)
return mat3(0.0);
// Calculate the transpose...
mat3 MatrixT = transpose(Matrix);
// Calculate needed determinants...
float D00 = MatrixT[1][1] * MatrixT[2][2] + MatrixT[2][1] * MatrixT[1][2];
float D10 = MatrixT[0][1] * MatrixT[2][2] + MatrixT[2][1] * MatrixT[0][2];
float D20 = MatrixT[0][1] * MatrixT[1][2] + MatrixT[1][1] * MatrixT[0][2];
float D01 = MatrixT[1][0] * MatrixT[2][2] + MatrixT[2][0] * MatrixT[1][2];
float D11 = MatrixT[0][0] * MatrixT[2][2] + MatrixT[2][0] * MatrixT[0][2];
float D21 = MatrixT[0][0] * MatrixT[1][2] + MatrixT[1][0] * MatrixT[0][2];
float D02 = MatrixT[1][0] * MatrixT[2][1] + MatrixT[2][0] * MatrixT[1][1];
float D12 = MatrixT[0][0] * MatrixT[2][1] + MatrixT[2][0] * MatrixT[0][1];
float D22 = MatrixT[0][0] * MatrixT[1][1] + MatrixT[1][0] * MatrixT[0][1];
// Assemble matrix of cofactors...
mat3 MatrixAdjugate;
MatrixAdjugate[0] = vec3( D00, -D01, D02);
MatrixAdjugate[1] = vec3(-D10, D11, -D12);
MatrixAdjugate[2] = vec3( D20, -D21, D22);
// Calculate the inverse...
return (1.0 / D) * MatrixAdjugate;
}
// Entry point...
void main()
{
// Variables...
float Specular;
mat4 ModelViewProjectionMatrix = ProjectionMatrix * ModelViewMatrix;
mat3 NormalMatrix = inverse(mat3(transpose(ModelViewMatrix)));
// Calculate the vertex position in eye coordinates...
vec3 ecPosition = vec3(ModelViewMatrix * mcVertex);
// Calculate the normalized vector to the light source from vertex...
vec3 ecLightVector = normalize(ecLightPosition - ecPosition);
// Calculate the normal vector in eye coordinates...
vec3 ecNormalVector = normalize(NormalMatrix * mcNormal);
// Calculate vector to viewer from vertex (viewer is origin in eye coordinates)
vec3 ecViewerVector = normalize(-ecPosition);
// Given the vector from surface to light and normal, compute reflected ray...
vec3 ecReflectionVector = reflect(-ecLightVector, ecNormalVector);
// Diffuse light at this vertex is a function of how coincident normal and
// the incident light wave are...
float Diffuse = max(dot(ecLightVector, ecNormalVector), 0.0);
// Specular light at this vertex is a function of how coincident normal and
// viewer are, but don't waste time if surface doesn't even face the light...
if(Diffuse > 0.0)
{
// Calculate...
Specular = max(dot(ecReflectionVector, ecViewerVector), 0.0);
// Amplify...
Specular = pow(Specular, 16.0);
}
else
Specular = 0.0;
// Output light intensity to be interpolated for fragment shader...
LightIntensity = (Diffuse * DiffuseContribution) +
(Specular * SpecularContribution);
// Output vertex position in clipping coordinates...
gl_Position = ModelViewProjectionMatrix * mcVertex;
// Output vertex position to be interpolated for fragment shader...
mcPosition = mcVertex.xy;
}
Any help appreciated.
Kip