index.html

html · 163 lines · part of Raytracer 002 - Diffuse and phong lighting · raw

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

<script src="webgl_fragment_framework.001.js"></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;

  vec3 ray;
  vec3 dir;

  vec4 sphere_pos[3];
  vec3 sphere_col[3];

  float intersectSphere( in vec3 ray, in vec3 dir, in vec3 sphere_pos, in float radius )
  {
    float x = sphere_pos.x;
    float y = sphere_pos.y;
    float z = sphere_pos.z;

    float a, b, c, d, t1, t2;

    a = dir.x * dir.x + dir.y * dir.y + dir.z * dir.z;
    b = 2.0 * (dir.x * (ray.x - x) + dir.y * (ray.y - y) + dir.z * (ray.z - z));
    c = (ray.x - x) * (ray.x - x) + (ray.y - y) * (ray.y - y) + (ray.z - z) * (ray.z - z) - radius * radius;
    d = b * b - 4.0 * a * c;

    if( d <= 0.0 ) return 0.0;

    d = sqrt(d);

    t2 = (-b + d) / (2.0 * a);
    t1 = (-b - d) / (2.0 * a);

    if( t1 > t2 ) return t2;
    return t1;
  }

  int intersect( in vec3 ray, in vec3 dir, out vec3 col, out vec3 pos, out vec3 normal, out vec3 reflection )
  {
    float max_t = 9999999.0;
    int found_i = -1;

    for( int i = 0; i<3; i++ )
    {
      float t = intersectSphere( ray, dir, sphere_pos[i].xyz, sphere_pos[i].w );

      if( t > 0.0001 && t < max_t )
      {
        max_t = t;
        found_i = i;
      }
    }

    if( found_i == -1 )
    {
      col = vec3( 0.0, 0.0, 0.0 );
      pos = vec3( 0.0 );
      normal = vec3( 0.0 );
      reflection = vec3( 0.0 );
      return -1;
    }

    for( int i = 0; i<3; i++ )
    {
      if( found_i == i )
      {
        pos = ray + max_t * dir;

        normal = (pos - sphere_pos[i].xyz) / sphere_pos[i].w;

        reflection = dir - 2.0*normal*dot( dir, normal );

        col = sphere_col[i];
      }
    }

    return found_i;
  }

  void main(void)
  {
    sphere_pos[0] = vec4( -1.0, 0.0, 4.0, 0.5);
    sphere_col[0] = vec3( 0.5, 0.0, 1.0 );

    sphere_pos[1] = vec4( 1.0, 0.5, 3.0, 0.8 );
    sphere_col[1] = vec3( 1.0, 0.75, 0.0 );

    sphere_pos[2] = vec4( 0.2, -0.75, 3.5, 0.75);
    sphere_col[2] = vec3( 0.75, 1.0, 0.0 );

    ray = vec3( 0.0, 0.0, 0.0 );
    dir = normalize( vPosition );

    vec3 col;
    vec3 pos;
    vec3 normal;
    vec3 reflection;

    vec3 light = vec3( -0.5, 3.0, 2.0 );

    for( int i=0; i<3; i++ )
    {
      float x = 1.3*sin( float(i)*2.1768 - uTime*(0.3762+float(i)*0.1298) );
      float y = 1.3*sin( float(i)*3.1897 + uTime*(0.2467+float(i)*0.3178) );
      float z = 1.3*sin( float(i)*0.1123 + uTime*(0.3112+float(i)*0.5512) );

      sphere_pos[i] = vec4( x, y, z + 4.0, sphere_pos[i].w );
    }

    int sphere_index = intersect( ray, dir, col, pos, normal, reflection );

    if( sphere_index == -1 )
    {
      col = vec3( 0.25 ) * dir.z;
    }
    else
    {
      vec3 light_dir = normalize( light - pos );

      col *= max( dot( normal, light_dir ), 0.0 )*0.8 + 0.2;

      float phong = pow( max( dot( reflection, light_dir ), 0.0 ), 17.0 );

      col = vec3( 1.0, 1.0, 1.0 ) * phong + col*(1.0-phong);
    }

    gl_FragColor = vec4( col, 1.0 );
  }

</script>

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

<table cellspacing="0" cellpadding="0" border="0" width="100%" height="100%"><tr><td align="center" valign="middle">
<table cellspacing="0" cellpadding="0" border="0" width="640">
  <tr>
    <td style="padding:8px;background:#555555;color:#FFFFFF;font-family:arial;font-size:11px;font-weight:bold">
      <div>WebGL Fragment Shader Raytracer - 3 Spheres - Basic per-pixel phong and specular lighting</div>
    </td>
  </tr>
  <tr>
    <td><canvas id="canvas" width="640" height="640" 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>