demotool/shaders/raymarcher.glsl

145 lines
3.4 KiB
GLSL

vec3 getNormal( vec3 pos )
{
vec2 v = vec2( .0005 , 0 );
return normalize( vec3(
map( pos + v.xyy ).x - map( pos - v.xyy ).x ,
map( pos + v.yxy ).x - map( pos - v.yxy ).x ,
map( pos + v.yyx ).x - map( pos - v.yyx ).x ) );
}
// -----------------------------------------------------------------------------
vec3 RM_Basic( vec3 o , vec3 d , int steps , float factor )
{
int i = 0;
float dist = .01 , mat = -1;
for ( ; i < steps ; ++ i ) {
vec2 res = map( o + d * dist );
if ( abs( res.x ) < u_Render.z || dist > u_Render.w ) {
break;
}
dist += res.x * factor;
mat = res.y;
}
return vec3( dist , dist >= u_Render.w ? -1 : mat , i );
}
vec3 RM_Advanced( vec3 o , vec3 d , int steps , float factor )
{
const float dMin = .1 , dMax = u_Render.w , pixel = u_Render.z;
int i = 0;
float dist = dMin , mat = -1;
float omega = factor;
float cError = 1 / 0. , cDist = dMin;
float pRad = 0 , sLen = 0;
for ( ; i < steps ; ++ i ) {
vec2 res = map( o + d * dist );
float rad = abs( res.x );
bool sorFail = omega > 1 && ( rad + pRad ) < sLen;
if ( sorFail ) {
sLen -= omega * sLen;
omega = 1;
} else {
sLen = res.x * omega;
}
pRad = rad;
float error = rad / dist;
if ( !sorFail && error < cError ) {
cError = error;
cDist = dist;
}
if ( !sorFail && error < pixel || dist > dMax ) {
break;
}
dist += sLen;
}
if ( dist <= dMax && cError <= pixel ) {
return vec3( cDist , map( o + d * cDist ).y , i );
}
return vec3( cDist , -1 , steps );
}
// -----------------------------------------------------------------------------
void main( )
{
setCamFromUniforms( );
vec2 uv = ( gl_FragCoord.xy / u_Resolution ) * 2 - 1;
vec3 camDir = normalize( lookAt - camPos );
vec3 side = normalize( cross( camUp , camDir ) );
vec3 up = normalize( cross( camDir , side ) );
vec3 rayDir = normalize( camDir * nearPlane
+ uv.x * side * u_Resolution.x / u_Resolution.y
+ uv.y * up );
vec3 r = RM_Advanced( camPos , rayDir , int( u_Render.x ) , u_Render.y );
vec3 hitPos = camPos + rayDir * r.x;
vec3 bc = vec3( 0 );
if ( r.y >= 0. ) {
const int midx = int( r.y );
const vec3 normal = getNormal( hitPos );
const vec3 lightDir = normalize( -u_LightDir );
#if defined( USE_BP )
// Blinn-Phong only
bc = BP_Shade( BPMaterials[ midx ] ,
rayDir , normal , lightDir );
#else
#if defined( USE_PBR )
// PBR only
T_PBRMaterialOld material = PBRMaterialsOld[ midx ];
T_PBRPrecomputedOld precomputed = PBR_PrecomputeOld(
material , rayDir , normal );
bc = PBR_ShadeOld( material , precomputed ,
rayDir , normal , lightDir );
#else
#if defined( USE_MAP_MATERIAL )
// Remap materials through mapMaterials
int mtype , mtidx , glowidx;
mapMaterial( midx , mtype , mtidx , glowidx );
if ( mtype == 0 ) {
bc = BP_Shade( BPMaterials[ mtidx ] ,
rayDir , normal , lightDir );
} else {
#if 0
T_PBRMaterialOld material = PBRMaterialsOld[ mtidx ];
T_PBRPrecomputedOld precomputed = PBR_PrecomputeOld(
material , rayDir , normal );
bc = PBR_ShadeOld( material , precomputed ,
rayDir , normal , lightDir );
#else
bc = PBR_Shade( PBRMaterials[ mtidx ] ,
-rayDir , normal , lightDir );
#endif
}
#if defined( USE_GLOW )
if ( glowidx >= 0 ) {
bc += Glow[ glowidx ];
}
#endif
#endif
#endif
#endif
#ifdef USE_GLOW
#ifndef USE_MAP_MATERIAL
bc += Glow[ midx ];
#endif
#endif
}
o_Color = bc;
o_Z = r.x;
}