index.html
html · 202 lines · part of Raytracer 005 - More spheres · 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[6];
vec3 sphere_col[6];
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<6; i++ )
{
float t = intersectSphere( ray, dir, sphere_pos[i].xyz, sphere_pos[i].w );
if( t > 0.0 && 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<6; 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];// + vec3( 0.1*sin(max_t*10), 0.1*sin(max_t*10), 0.1*sin(max_t*10) );
}
}
return found_i;
}
bool intersect_shadow( in vec3 ray, in vec3 dir )
{
for( int i = 0; i<6; i++ )
{
float t = intersectSphere( ray, dir, sphere_pos[i].xyz, sphere_pos[i].w );
if( t > 0.0 )
{
return false;
}
}
return true;
}
void main(void)
{
vec3 ray = vec3( 0.0, 0.0, 0.0 );
vec3 dir = normalize( vPosition );
vec3 final_col;
vec3 col;
vec3 pos;
vec3 normal;
vec3 reflection;
vec3 light = vec3( -0.5, 2.0, 2.0 );
for( int i=0; i<6; i++ )
{
float ii = float(i);
float x = 1.3*sin(ii*2.13 + uTime*(0.6762+ii*0.163));
float y = 1.3*sin(ii*1.13 + uTime*(0.8467+ii*0.193));
float z = 3.0 + 0.3*sin(ii*4.13 + uTime*(1.1112+ii*0.183));
float w = 0.5 + 0.2*sin(ii*4.13 + uTime*0.01*(1.1112+ii*0.183));
sphere_pos[i] = vec4( x, y, z, w );
sphere_col[i] = vec3( 1.0-ii/12.0, 1.0-ii/6.0, 0.1 + ii/12.0 );
}
// 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 = light - pos;
if( intersect_shadow( pos+light_dir*0.0000001, light_dir ) )
{
light_dir = normalize( light_dir );
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);
}
else
{
col *= 0.2;
}
final_col = col;
sphere_index = intersect( pos+reflection*0.0000001, reflection, col, pos, normal, reflection );
if( sphere_index >= 0 )
{
vec3 light_dir = light - pos;
if( intersect_shadow( pos+light_dir*0.0001, light_dir ) )
{
light_dir = normalize( light_dir );
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);
}
else
{
col *= 0.2;
}
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 - More Spheres - Per-pixel reflections and shadows</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>