index.html
html · 189 lines · part of Raytracer 003 - 3 levels of reflection · 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 );
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 final_col;
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 = sphere_pos[i].x + 1.3*sin(sphere_pos[i].y*2.13 + uTime*(0.6762+sphere_pos[i].z*0.163));
float y = sphere_pos[i].y + 1.3*sin(sphere_pos[i].z*1.13 + uTime*(0.8467+sphere_pos[i].x*0.193));
float z = sphere_pos[i].z + 0.3*sin(sphere_pos[i].x*4.13 + uTime*(1.1112+sphere_pos[i].y*0.183));
sphere_pos[i] = vec4( x, y, z, sphere_pos[i].w );
}
// Intersect first ray
int sphere_index = intersect( ray, dir, col, pos, normal, reflection );
if( sphere_index == -1 )
{
final_col = vec3( 0.25 ) * dir.z;
}
else
{
// Calculate colour of surface
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);
final_col = col;
sphere_index = intersect( pos+reflection*0.0001, reflection, col, pos, normal, reflection );
if( sphere_index >= 0 )
{
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);
final_col = final_col*0.5 + col*0.5;
sphere_index = intersect( pos+reflection*0.0001, reflection, col, pos, normal, reflection );
if( sphere_index >= 0 )
{
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);
final_col = final_col*0.75 + col*0.25;
}
}
}
gl_FragColor = vec4( final_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 - Recursive reflection</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"> </div>
</td>
</tr>
</table>
</td></tr></table>
</body>
</html>