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; }