demotool/shaders/lib/raymarching.glsl

90 lines
1.8 KiB
GLSL

//! type library
vec2 RM_Map( in vec3 pos );
// -----------------------------------------------------------------------------
vec3 RM_GetNormal(
in vec3 pos )
{
vec2 v = vec2( .0005 , 0 );
return normalize( vec3(
RM_Map( pos + v.xyy ).x - RM_Map( pos - v.xyy ).x ,
RM_Map( pos + v.yxy ).x - RM_Map( pos - v.yxy ).x ,
RM_Map( pos + v.yyx ).x - RM_Map( pos - v.yyx ).x ) );
}
// -----------------------------------------------------------------------------
vec3 RM_Basic(
in vec3 origin ,
in vec3 direction ,
in int steps ,
in float factor ,
in float epsilon ,
in float dMin ,
in float dMax )
{
int i = 0;
float dist = dMin , mat = -1;
for ( ; i < steps ; ++ i ) {
vec2 res = RM_Map( origin + direction * dist );
if ( abs( res.x ) < epsilon || dist > dMax ) {
break;
}
dist += res.x * factor;
mat = res.y;
}
return vec3( dist , dist >= dMax ? -1 : mat , i );
}
vec3 RM_Advanced(
in vec3 origin ,
in vec3 direction ,
in int steps ,
in float factor ,
in float epsilon ,
in float dMin ,
in float dMax )
{
int i = 0;
float dist = dMin ,
omega = factor ,
cError = 1 / 0. ,
cDist = dMin ,
pRad = 0 ,
sLen = 0;
for ( ; i < steps ; ++ i ) {
vec2 res = RM_Map( origin + direction * 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 < epsilon || dist > dMax ) {
break;
}
dist += sLen;
}
if ( dist <= dMax && cError <= epsilon ) {
return vec3( cDist , RM_Map( origin + direction * cDist ).y , i );
}
return vec3( cDist , -1 , steps );
}