home dev games gallery work
Lewpen.com»Research & Development»3D Graphics»WebGL»GLSL Raycasting»Cathedral (higher detail)

Cathedral (higher detail)

More raycasting steps for a sharper image

/ index.html

<html>
<title>WebGL Fragment Shader Canvas</title>

<script src="webgl_fragment_framework.js?download"></script>

<script id="shader" type="x-shader/x-fragment">

  #ifdef GL_ES
  precision mediump float;
  #endif

  varying vec3 vPosition;
  uniform float uTime;
  uniform vec2 uMousePos;

//ifs
float fu; //fractal_spheresubstract
float fd; //fractal_distancemult
vec3 cs;  //fractal_csize
float fs; //fractal_size
vec3 fc;  //fractal_c

vec2 rs;  //resolution

//camera
vec3  cp; //camera position
mat3  cr; //camera rotation




float dE(vec3 p) {
   float dEfactor=1.;
   //int fractal_iterations = 12;
   for(int i=0;i<12;i++){
      //box folding
      p=2.*clamp(p, -cs, cs)-p;
      //inversion
      float k=max(fs/dot(p,p),1.);
      p*=k;
      dEfactor*=k;
      //julia seed
      p+=fc;
   }
   //call basic shape and scale its DE
   //need to adjust fractal_distancemult with non zero julia seed
   float rxy=length(p.xy)-fu;
   //distance from pos to the pseudo kleinian basic shape ...
   return (fd*max(rxy,abs(length(p.xy)*p.z)/sqrt(dot(p,p)))/abs(dEfactor));
}

float rd(vec2 fragment_coordinates) {   
   //calculate ray direction from fragment coordinates ...
   vec2 ray_position = fragment_coordinates;//(0.5*rs-fragment_coordinates)/vec2(rs.x,-rs.y);
   ray_position.x *= (rs.x/rs.y); //aspect_ratio
   vec3 ray_direction = normalize(cr * vec3(ray_position.x * vec3(1, 0, 0) + ray_position.y * vec3(0, 1, 0) - .9 * vec3(0, 0, 1)));
   //sphere tracing initialization ...
   float ray_length = 0.0;
   vec3  ray = cp+ray_length*ray_direction;
   float epsilon = 0.0000006;
   float  calculated_distance;
   int   tracingsteps = 0;
   bool  hit = false;
   ray = cp+ray_length*ray_direction;
   //magic :) DO NOT TOUCH!
   float eps_factor = 2.0*0.743294*(1.0/rs.y)*.6;
   //actual sphere tracing ...
   //#define tracingsteps_max 200
   for (int i=0; i<50; i++) {
      tracingsteps = i;
      calculated_distance = dE(ray);     
      //small stepback to remove 'fuzzel'-structures near inside shooting range
      //#define raylength_max 10000.0
      if (hit && calculated_distance<epsilon || ray_length>10000.) {
         tracingsteps--;
         break;
      }
      hit = false;
      ray_length += calculated_distance;
      ray = cp+ray_length*ray_direction;
      epsilon = ray_length * eps_factor;
      if (calculated_distance<epsilon) {
         hit = true;
      }
   }
   //---   
   //intersects ?
   //#define tracingsteps_max 200
//   return float(tracingsteps)/float(40);
/*
      float epsilon_normal = 1.5e-7;
      vec3 normal = normalize(vec3(
         dE(ray+vec3(epsilon_normal, 0, 0))-dE(ray-vec3(epsilon_normal, 0, 0)),
         dE(ray+vec3(0, epsilon_normal, 0))-dE(ray-vec3(0, epsilon_normal, 0)),
         dE(ray+vec3(0, 0, epsilon_normal))-dE(ray-vec3(0, 0, epsilon_normal)))
      );
*/
    return ray_length * 20.2;// + 0.1 + 0.1 * dot( normal, vec3( 0.707, 0.0, 0.707 ) );
}

//return rotation matrix for rotating around vector v by angle
mat3 mr(vec3 v, float angle) {
    float c = cos(radians(angle));
    float s = sin(radians(angle));
    return mat3(c+(1.0-c)*v.x*v.x   , (1.0-c)*v.x*v.y-s*v.z  , (1.0-c)*v.x*v.z+s*v.y,
               (1.0-c)*v.x*v.y+s*v.z, c+(1.0-c)*v.y*v.y      , (1.0-c)*v.y*v.z-s*v.x,
               (1.0-c)*v.x*v.z-s*v.y, (1.0 - c)*v.y*v.z+s*v.x, c+(1.0-c)*v.z*v.z);
}

  void main(void)
  {
    float camera_roll = 0.;
    float camera_pitch = 90.;
    float camera_yaw = 0.;

    vec2 custom_glFragCoord = gl_FragCoord.xy;    

float temp_scenetimer = 200.0 - uTime * 10.0;

    fu = 10.0;
    fd = 0.763;
    cs = vec3(0.80800,0.80800,1.16700);
    fs = 1.0;
    fc = vec3(0.0);
    rs = vec2( 300.0, 300.0 );

    camera_pitch = 23.9;
    cp = vec3(0.8,-1.16339+16.0-uTime*0.395,-1.80153);
    cs.y = 0.58000;

       fu = 1.01000;
       cp = vec3(0.0007,0.02000,0.10000-temp_scenetimer*0.00028);
       camera_pitch = 0.0;
       camera_yaw = temp_scenetimer*0.009*180.0;
       cs.x = 0.90000;

    cr = mat3( 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 );
    cr = mr(vec3(0, 1, 0), 180.0 - camera_yaw) * mr(vec3(1, 0, 0), -camera_pitch) * mr(vec3(0, 0, 1), camera_roll);    

    float a = rd( vec2( vPosition.x, vPosition.y ) );

    gl_FragColor = vec4( a, a, a, 1.0 );
  }


</script>

<body onload="webgl_init( 'canvas', 'shader', 'status' )" bgcolor="#000000">

<table cellspacing="0" cellpadding="0" border="0" width="100%" aheight="100%"><tr><td align="center" valign="middle">
<table cellspacing="0" cellpadding="0" border="0" width="200">
  <tr>
    <td style="padding:8px;background:#555555;color:#FFFFFF;font-family:arial;font-size:11px;font-weight:bold">
      <div>WebGL GLSL Raycaster</div>
    </td>
  </tr>
  <tr>
    <td><canvas id="canvas" width="300" height="300" style="border:5px solid #FFFFFF"></canvas></td>
  </tr><tr>
    <td style="padding:8px;background:#555555;color:#FFFFFF;font-family:arial;font-size:11px;font-weight:bold">
      <div id="status">&nbsp;</div>
    </td>
  </tr>
</table>
</td></tr></table>


</body>
</html>
Related Articles

First test of fractal casting in a shader

Moving more quickly through the scene

Alternative fractal parameters

Fewer raycasting steps for fog effect

Reference GLSL Raycaster

Games

The Dodge Game
Flatspace

2-Player Games:

Quake 2D
Meteora

Puzzle Games:

Mini Tetris
Sudoku Solver

Development

3D Graphics:

3D Graphics Articles
WebGL Examples
OpenGL Examples
Flash 3D Engine
Java 3D Engine

Development:

Programming Articles
Game Development Examples

Work

Portfolio
Clients
Startups & Projects
Expertise

Links

CubeLogix Studios
PHP Charts & Graphs
Local Legends Football