Curved Relief Mapping

Hi guys!

I ve been trying to port this cg shader to glsl… relief mapping is one thing but the curved is another… I believe it is a must to understand and frankly… it is amazing… check this out:

http://fabio.policarpo.nom.br/docs/Curved_ReliefMapping.pdf
http://fabio.policarpo.nom.br/files/reliefmap4.zip
if anyone is interested in helping digging this out… fun is on its way! :slight_smile:

here is what ShaderDesigner as to offer as a starter:

vert

uniform mat4 matWorldView;
uniform mat4 matView;
uniform mat4 matWorldViewProjection;

attribute vec3 tangent; 
attribute vec3 binormal;

varying vec2 texCoord;
varying vec3 eyeSpaceVert;
varying vec3 eyeSpaceTangent;
varying vec3 eyeSpaceBinormal;
varying vec3 eyeSpaceNormal;
varying vec3 eyeSpaceLight;

void main(void)
{ 
   eyeSpaceVert = (gl_ModelViewMatrix * gl_Vertex).xyz;
  // eyeSpaceLight = (gl_ModelViewMatrix * vec4(gl_LightSource[0].position.xyz,1.0)).xyz;
  eyeSpaceLight = vec4(gl_LightSource[0].position.xyz,1.0).xyz;
                       
   eyeSpaceTangent  = gl_NormalMatrix * tangent;
   eyeSpaceBinormal = gl_NormalMatrix * binormal;
   eyeSpaceNormal   = gl_NormalMatrix * gl_Normal;
   
   texCoord   = gl_MultiTexCoord0.xy;
   
   gl_Position = ftransform();
}

frag

uniform vec4 ambient;
uniform vec4 specular;
uniform vec4 diffuse;
uniform float shine;
uniform float depth;
uniform float tile;
uniform int linear_search_steps;
uniform int binary_search_steps;
   
varying vec2 texCoord;
varying vec3 eyeSpaceVert;
varying vec3 eyeSpaceTangent;
varying vec3 eyeSpaceBinormal;
varying vec3 eyeSpaceNormal;
varying vec3 eyeSpaceLight;

uniform sampler2D reliefmap;
uniform sampler2D texmap;
uniform sampler2D gloss;

float ray_intersect_rm(in vec2 dp,in vec2 ds);

void main(void)
{
   vec4 t,c;
   vec3 p,v,l,s;
   vec2 dp,ds,uv;
   float d,a;

   // ray intersect in view direction
   p  = eyeSpaceVert;
   v  = normalize(p);
   a  = dot(eyeSpaceNormal,-v);
   s  = normalize(vec3(dot(v,eyeSpaceTangent),dot(v,eyeSpaceBinormal),a));
   s  *= depth/a;
   dp = texCoord*tile;
   ds = s.xy;
   d  = ray_intersect_rm(dp,ds);
   
   // get rm and color texture points
   uv=dp+ds*d;
   t=texture2D(reliefmap,uv);
   c=texture2D(texmap,uv);

   // expand normal from normal map in local polygon space
   t.xy=t.xy*2.0-1.0;
   t.z=sqrt(1.0-dot(t.xy,t.xy));
   t.xyz=normalize(t.x*eyeSpaceTangent+t.y*eyeSpaceBinormal+t.z*eyeSpaceNormal);

   // compute light direction
   p += v*d*a;
   l=normalize(p-eyeSpaceLight.xyz);
   
   // ray intersect in light direction
   dp+= ds*d;
   a  = dot(eyeSpaceNormal,-l);
   s  = normalize(vec3(dot(l,eyeSpaceTangent),dot(l,eyeSpaceBinormal),a));
   s *= depth/a;
   ds = s.xy;
   dp-= ds*d;
   float dl = ray_intersect_rm(dp,s.xy);
   float shadow = 1.0;
   vec3 specular_shadow=specular.xyz;
   if (dl<d-0.05) // if pixel in shadow
   {
      shadow=dot(ambient.xyz,vec3(1.0))*0.333333;
      specular_shadow=vec3(0.0);
   }

   // compute diffuse and specular terms
   float att=max(0.0,dot(-l,eyeSpaceNormal));
   float diff=shadow*max(0.0,dot(-l,t.xyz));
   float spec=max(0.0,dot(normalize(-l-v),t.xyz));

   // compute final color
   vec4 finalcolor;
   finalcolor.xyz=ambient.xyz*c.xyz+
      att*(c.xyz*diffuse.xyz*diff+specular_shadow*pow(spec,shine));
   finalcolor.w=1.0;   
   gl_FragColor = vec4(finalcolor.rgb,1.0);
   
}

float ray_intersect_rm(in vec2 dp, in vec2 ds)
{
   //const int linear_search_steps=20;
   //const int binary_search_steps=5;
   float depth_step=1.0/float(linear_search_steps);

   // current size of search window
   float size=depth_step;
   // current depth position
   float depth=0.0;
   // best match found (starts with last position 1.0)
   float best_depth=1.0;

   // search front to back for first point inside object
   for( int i=0;i<linear_search_steps-1;i++ )
   {
      depth+=size;
      vec4 t=texture2D(reliefmap,dp+ds*depth);

      if (best_depth>0.996)   // if no depth found yet
      if (depth>=t.w)
         best_depth=depth;   // store best depth
   }
   depth=best_depth;
   
   // recurse around first point (depth) for closest match
   for( int i=0;i<binary_search_steps;i++ )
   {
      size*=0.5;
      vec4 t=texture2D(reliefmap,dp+ds*depth);
      if (depth>=t.w)
      {
         best_depth=depth;
         depth-=2.0*size;
      }
      depth+=size;
   }

   return best_depth;
}

I have to know, has anyone gotten the Typhoon Labs relief shader implemented into their program perfectly?

I have been trying to implement it, but it turns out more like bump mapping than relief. So it is not doing any overlapping/occlusion with the texture.

If someone has it working, can you tell me what you had to change, if anything, and the attribute and uniform variables you are using in your shader.

Thanks

for my part, most of the work was to calculate the tangent and bitangents client side correctly… send them via vertex attributes and thats it!

Hmm, that must be what I am doing wrong.

Is there any reason why I must use vertex attributes and not just generate them in the shader?

Thanks

Is there any reason why I must use vertex attributes and not just generate them in the shader?
Assuming you are refering to tangents and binormals, to compute them in the shader you would need either:

  1. For each vertex, a list of all neighboring vertices and their texture coordinates and normals, OR
  2. A differentiable formula for the surface from which you could compute the gradient in the shader.

Either way, you’d be needlessly recomputing the tangents and binormals each frame. Performance-wise, you’d be better off computing them once in a preprocessing stage and passing them in as vertex attributes. But if your mesh is deformable or otherwise non-static, you’d need to recompute the tangent space basis each time the surface changes.

I’m interested in this technique. Unfortunately, the original ressources are offline:

http://fabio.policarpo.nom.br/files/reliefmap4.zip

Does anyone by chance have this file and would be so kind to upload it to a one click hoster and send me the link? That would be awesome.

Regards

http://http.developer.nvidia.com/GPUGems3/gpugems3_ch18.html

This should be the same thing. BTW, 2 second Google search…

I know (R)CSM and it’s not the same thing. It does not support correct silhouettes (as it is there). Also, there’s no z-buffer correction for shadow mapping in it. I refer to this paper

and I’d really like to have the corresponding demos / ressouces that once were available.

Well, I guess you’re right. Still the papers complement each other quite well. :wink:

Manuel Oliveira’s page also links to the dead links above. I guess the easiest and most rewarding way to get this straight is to implement it yourself.

Yes, but I’m struggling a bit with that. Especially the pre-processing (calculating the quadric coefficients).

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