Kip Warner

01-16-2010, 12:01 AM

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

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