How to Compute the Position and Normal in the Vertex Shader in OpenGL (GLSL) and Direct3D (HLSL)



How to... Compute the Position and Normal in the Vertex Shader in OpenGL and Direct3D

This howto is valid for all versions of OpenGL (2, 3, and 4) as well as all version of Direct3D (9, 10 and 11). I give code snippets in OpenGL 2 and Direct3D 9. OpenGL 3 / 4 or Direct3D 10 / 11 codes can be easily derived from the GL2 / D3D9 ones.

To compute the tranformed position (gl_Position in GLSL, clipping space), you need three matrices: projection, view and model. Projection and view matrices are camera matrices and model matrix is the transformation matrix of the current object being rendered.

The three matrices are passed to the vertex shader as input variables (uniform in GLSL) by the host application.

In the following vertex shaders, P is the XYZ position of the vertex in local space or object space: the position without any transformation. Same thing for N, the vertex normal in local space without any transformation.



OpenGL 2 / GLSL vertex shader:

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

varying vec3 normal;

void main()
{
  vec3 P = gl_Vertex.xyz; 
  vec3 N = gl_Normal.xyz; 
  
  mat4 modelView = viewMatrix * modelMatrix;
  mat4 modelViewProjection = projectionMatrix * modelView;
  gl_Position = modelViewProjection * vec4(P, 1.0);
  
  normal = modelView * vec4(N, 0.0);
}

Direct3D 9 / HLSL vertex shader:

float4x4 projectionMatrix;
float4x4 viewMatrix;
float4x4 modelMatrix;

struct VS_OUTPUT
{
  float4 Position : POSITION;
  float3 Normal: TEXCOORD0;
};

VS_OUTPUT VertexShaderD3D(float4 P : POSITION, float3 N : NORMAL)
{
  VS_OUTPUT o;
  float4x4 modelView = mul(modelMatrix, viewMatrix);
  float4x4 modelViewProjection = mul(modelView, projectionMatrix);
  o.Position = mul(float4(P.xyz, 1.0), modelViewProjection);
  o.Normal = mul(N, (float3x3)modelView); 
  return o;
}



Remark: OpenGL matrix convention is column-major order while Direct3D convention is row-major order. That explains why the order of matrices multiplication is not the same in OpenGL and Direct3D.



And if you want to play with the GLSL shader (with live coding), you can find it in GeeXlab code samples pack in the GLSL_ComputePosNorm/ folder of the zip archive. The latest version of GeeXLab is available HERE.

GeeXLab demo, How to Compute the Position and Normal in the Vertex Shader in OpenGL


Just launch GeeXLab and drag-n-drop the demo file (GLSL_Compute_PosNorm.xml) into GeeXLab, that’s all.




Geeks3D.com

↑ Grab this Headline Animator