Compute fragment's ray direction (world's coordinates)

Hello !

I try to make a sky shader using a fullscreen quad and an equirectangular texture (Equirectangular Projection - PanoTools.org Wiki ). So for each fragment I need the “raytracing direction” in (polar) spherical coordinates. I need to someone check if the following method seems good …

Send vertices :

I send directly to the vertex shader the fullscreen quad’s clip coordinates :


  glBegin(GL_QUADS);
  glVertex2i(-1,-1);
  glVertex2i(1,-1);
  glVertex2i(1, 1);
  glVertex2i(-1,1);
  glEnd();

The vertex shaders :

I compute de ray direction for each (four) vertex using clip coordinates. First I make inverse projection and next inverse modelview but without translation.


/*****************/
/* VERTEX SHADER */
/*****************/

varying vec3 rayDirection;

void main()
{
  vec4 reverseVec;

  /* inverse perspective projection */
  reverseVec = vec4(gl_Vertex.xy, 0.0, 1.0);
  reverseVec *= gl_ProjectionMatrixInverse;

  /* inverse modelview, without translation */
  reverseVec.w = 0.0;
  reverseVec *= gl_ModelViewMatrixInverse;
  
  /* send */
  rayDirection = vec3(reverseVec);
  gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);

}

I’am not sure that I set the z and w coordinates to good values …

The fragment shaders :

The rayDirection vector is interpolated, so I get the ray direction in world’s coordinates. So I just need to compute the spherical direction (s, t).


/*******************/
/* FRAGMENT SHADER */
/*******************/

varying vec3 rayDirection;

const float PI = 3.14159265358979323846264;

void main()
{
  vec3 normalizedDirection;
  vec2 polarDirection;
 
  /* T computation */
  normalizedDirection  = normalize(rayDirection);
  polarDirection.t = acos(normalizedDirection.y);

  /* S computation */
  rayDirection.y = 0.0;
  normalizedDirection  = normalize(rayDirection);
  
  if(normalizedDirection.x >= 0)
    polarDirection.s = acos(-normalizedDirection.z);
  else    
    polarDirection.s = acos(normalizedDirection.z) + PI;
 
  .....
 
}

It seems good ??

I finally found the error !! The problem is that

reverseVec *= gl_ProjectionMatrixInverse;

is equivalent to

reverseVec = reverseVec * gl_ProjectionMatrixInverse;

but not to

reverseVec = gl_ProjectionMatrixInverse * reverseVec ;

The shader now works ! It display an equirectangular panoramic image with :

Opengl side :


  glBegin(GL_QUADS);

  glVertex2i(-1, -1);
  glVertex2i(1, -1);
  glVertex2i(1, 1);
  glVertex2i(-1, 1);
  
  glEnd();


Vertex shader :


/*****************/
/* VERTEX SHADER */
/*****************/

varying vec3 rayDirection;

void main()
{
  vec4 reverseVec;

  /* inverse perspective projection */
  reverseVec = vec4(gl_Vertex.xy, 0.0, 1.0);
  reverseVec = gl_ProjectionMatrixInverse * reverseVec;

  /* inverse modelview, without translation */
  reverseVec.w = 0.0;
  reverseVec = gl_ModelViewMatrixInverse * reverseVec;
  
  /* send */
  rayDirection = vec3(reverseVec);
  gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);
}

Fragment shader :


/*******************/
/* FRAGMENT SHADER */
/*******************/

uniform sampler2D equiTex;
varying vec3 rayDirection;

const float PI = 3.14159265358979323846264;

void main()
{
  vec3 normalizedDirection;
  vec2 polarDirection;
 
  /* T computation */
  normalizedDirection  = normalize(rayDirection);
  polarDirection.t = acos(normalizedDirection.y)/PI;

  /* S computation */
  rayDirection.y = 0.0;
  normalizedDirection  = normalize(rayDirection);
  
  if(normalizedDirection.x >= 0)
    polarDirection.s = acos(-normalizedDirection.z)/(2*PI);
  else    
    polarDirection.s = (acos(normalizedDirection.z) + PI)/(2*PI);
  

  /* color */
  gl_FragColor = texture2D(equiTex, polarDirection.st);
 
}

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.