// vertex position IN view space (with model transformations)
float3 vpos=mul(glstate.matrix.modelview[0],pos).xyz;
// view in tangent space
float3 eye=mul(tangentspace,vpos);
eye.z=-eye.z;
OUT.eye=eye;
// light position in tangent space
OUT.light=mul(tangentspace,lightpos -vpos);
//OUT.light=mul(tangentspace,glstate.light[0].position.xyz -vpos);
return OUT;
}
// ray intersect quad depth map with linear search
void ray_intersect_rmqd_linear(
in sampler2D quad_depth_map,
inout float3 s,
inout float3 ds)
{
const int linear_search_steps=30; //15
ds/=linear_search_steps;
// search front to back for first point inside object
for( int i=0;i<linear_search_steps-1;i++ )
{
float4 t=tex2D(quad_depth_map,s.xy);
float4 d=s.z-t; // compute distances to each layer
d.xy*=d.zw; d.x*=d.y; // x=(x*y)*(z*w)
if (d.x>0) // if ouside object move forward
s+=ds;
}
}
// ray intersect quad depth map with binary search
void ray_intersect_rmqd_binary(
in sampler2D quad_depth_map,
inout float3 s,
inout float3 ds)
{
const int binary_search_steps=5;
float3 ss=sign(ds.z);
// recurse around first point for closest match
for( int i=0;i<binary_search_steps;i++ )
{
ds*=0.5; // half size at each step
float4 t=tex2D(quad_depth_map,s.xy);
float4 d=s.z-t; // compute distances to each layer
d.xy*=d.zw; d.x*=d.y; // x=(x*y)*(z*w)
if (d.x<0) // if inside
{
ss=s; // store good return position
s-=2*ds; // move backward
}
s+=ds; // else move forward
}
s=ss;
}
float4 relief_map_quad_depth(
v2f IN,
uniform sampler2D quad_depth_map,
uniform sampler2D color_map,
uniform sampler2D normal_map_x,
uniform sampler2D normal_map_y ) : COLOR
{
// view vector in tangent space
float3 v=normalize(IN.eye);
// serach start position
float3 s=float3(IN.texcoord,0);
// separate direction (front or back face)
float dir=v.z;
v.z=abs(v.z);
// if viewing from backface
if (dir<0)
{
s.z=0.996; // search from back to front
v.z=-v.z;
}
// ray intersect quad depth map
ray_intersect_rmqd_linear(quad_depth_map,s,v);
ray_intersect_rmqd_binary(quad_depth_map,s,v);
// discard if no intersection is found
if (s.z>0.997) discard;
if (s.z<0.003) discard;
// DEBUG: return depth
//return float4(s.zzz,1);
// get quad depth and color at intersection
float4 t=tex2D(quad_depth_map,s.xy);
float4 c=tex2D(color_map,s.xy);
// get normal components X and Y
float4 nx=tex2D(normal_map_x,s.xy);
float4 ny=tex2D(normal_map_y,s.xy);
// compute normal
float4 z=abs(s.z-t);
int m=0; // find min component
float zm = z.x;
if (z.y<zm) { m=1; zm = z.y; }
if (z.z<zm) { m=2; zm = z.z; }
if (z.w<zm) { m=3; }
float3 n; // get normal at min component layer
if ( m == 0) { n.x=nx[0]; n.y=1-ny[0]; } //n.x=nx[m]; n.y=1-ny[m];
if ( m == 1) { n.x=nx[1]; n.y=1-ny[1]; }
if ( m == 2) { n.x=nx[2]; n.y=1-ny[2]; }
if ( m == 3) { n.x=nx[3]; n.y=1-ny[3]; }
n.xy=n.xy*2-1; // expand to [-1,1] range
n.z=sqrt(max(0,1.0-dot(n.xy,n.xy))); // recompute z
if (m==1||m==3) // invert normal z if in backface
n.z=-n.z;
// DEBUG: return normal
// return float4(n*0.5+0.5,1);
// compute light vector in view space
float3 l=normalize(IN.light);
// restore view direction z component
v=normalize(IN.eye);
v.z=-v.z;
// compute diffuse and specular terms
float ldotn=saturate(dot(l,n));
float ndoth=saturate(dot(n,normalize(l-v)));