WebGL Beginner's Guide - Code / 1727_10 / ch10_Raytracing.html

<html>

<head>
<title>WebGL Beginner's Guide - Chapter 10 - Raytracing</title>
<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>

<!-- CSS Styles //-->
<link href='css/styles.css'   type='text/css' rel='stylesheet'>
<link href='css/prettify_desert.css'  type='text/css' rel='stylesheet'/>
<link href='css/colorpicker.css'  type='text/css' rel='stylesheet'/>

<link href='css/smoothness/jquery-ui-1.8.13.custom.css' type='text/css' rel='stylesheet' />
<!-- GUI Libraries //-->
<script type='text/javascript' src='js/gui/jquery-1.5.1.min.js'></script>
<script type='text/javascript' src='js/gui/jquery-ui-1.8.13.custom.min.js'></script> 
<script type='text/javascript' src='js/gui/colorpicker.js'></script>
<script type='text/javascript' src='js/gui/prettify.js'></script>
<script type='text/javascript' src='js/gui/codeview.js'></script>
<!-- MATH Libraries //-->
<script type='text/javascript' src='js/math/glMatrix-0.9.5.min.js'></script>
<!-- WEBGL Libraries //-->
<script type='text/javascript' src='js/webgl/Globals.js'></script>
<script type='text/javascript' src='js/webgl/Utils.js'></script>
<script type='text/javascript' src='js/webgl/Program.js'></script>
<script type='text/javascript' src='js/webgl/Scene.js'></script>
<script type='text/javascript' src='js/webgl/Axis.js'></script>
<script type='text/javascript' src='js/webgl/Floor.js'></script>
<script type='text/javascript' src='js/webgl/Camera.js'></script>
<script type='text/javascript' src='js/webgl/CameraInteractor.js'></script>
<script type='text/javascript' src='js/webgl/SceneTransforms.js'></script>
<script type='text/javascript' src='js/webgl/Texture.js'></script>
<script type='text/javascript' src='js/webgl/WebGLApp.js'></script>
<script type='text/javascript' src='js/webgl/PostProcess.js'></script>

<script id="post-common-vs" type="x-shader/x-vertex">
attribute vec2 aVertexPosition;
attribute vec2 aVertexTextureCoords;

varying vec2 vTextureCoord;

void main(void) {
    vTextureCoord = aVertexTextureCoords;
    gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}   
</script>

<!--http://glsl.heroku.com/e#1686.0-->
<script id="raytrace-fs" type="x-shader/x-fragment">
precision mediump float;

uniform float uTime;
uniform vec2 uInverseTextureSize;

vec3 lightDir = normalize( vec3(0.5, 0.5, 0.5) );
vec3 eyePos = vec3(0.0, 1.0, 4.0);
vec3 bgColor = vec3(0.2, 0.2, 0.2);

vec3 ambient = vec3(0.05, 0.1, 0.1);

vec4 sphere1 = vec4(0.0, 1.0, 0.0, 1.0);
vec3 sphere1Color = vec3(0.9, 0.8, 0.6);

float maxDist = 1024.0;

// ro is the ray origin, rd is the ray direction, and s is the sphere
float sphereInter( vec3 ro, vec3 rd, vec4 s ) {
    // Transform the ray into object space
    vec3 oro = ro - s.xyz;

    float a = dot(rd, rd);
    float b = 2.0 * dot(oro, rd);
    float c = dot(oro, oro) - s.w * s.w; // w is the sphere radius

    float d = b * b - 4.0 * a * c;

    if(d < 0.0) return d; // No intersection
    
    return (-b - sqrt(d)) / 2.0;
}

vec3 sphereNorm( vec3 pt, vec4 s ) {
    return ( pt - s.xyz )/ s.w;
}

float intersect( vec3 ro, vec3 rd, out vec3 norm, out vec3 color ) {
    float dist = maxDist;

    // If we wanted multiple objects in the scene you would loop through them here
    // and return the normal and color with the closest intersection point (lowest dist)

    float interDist = sphereInter( ro, rd, sphere1 ); 
    
    if ( interDist > 0.0 && interDist < dist ) {
        dist = interDist;

        vec3 pt = ro + dist * rd; // Point of intersection
        norm = sphereNorm(pt, sphere1); // Get normal for that point
        color = sphere1Color; // Get color for the sphere
    }

    return dist;
}

void main( void ) {
    // Pixel coordinate of the fragment being rendered
    vec2 uv = ( gl_FragCoord.xy * uInverseTextureSize );
    float aspectRatio = uInverseTextureSize.y/uInverseTextureSize.x;
    
    // Wiggle the sphere back and forth a bit
    sphere1.x = 1.5 * sin(uTime);
    sphere1.z = 0.5 * cos(uTime * 3.0);
    
    // Cast a ray out from the eye position into the scene
    vec3 ro = eyePos;
    // Ray we cast is tilted slightly downward to give a better view of the scene
    vec3 rd = normalize(vec3( -0.5 + uv * vec2(aspectRatio, 1.0), -1.0));
    
    vec3 rayColor = bgColor; // Default color if we don't intersect with anything

    // See if the ray intesects with any objects. 
    // Provides the normal of the nearest intersection point and color
    vec3 objNorm, objColor;
    float t = intersect(ro, rd, objNorm, objColor);
    
    if ( t < maxDist ) {
        float diffuse = clamp(dot(objNorm, lightDir), 0.0, 1.0); // diffuse factor
        rayColor = objColor * diffuse + ambient;
    }
    
    gl_FragColor = vec4(rayColor, 1.0);
}
</script>

<script id='code-js' type="text/javascript">

var camera 		= null;
var interactor 	= null;
var post 		= null;
var transforms	= null;

function configure(){
    gl.clearColor(0.3,0.3,0.3, 1.0);
    gl.clearDepth(100.0);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LESS);
	gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);
    
    //Creates and sets up the camera location
    camera = new Camera(CAMERA_ORBITING_TYPE);
    camera.goHome([0,0,40]);
    camera.setFocus([0.0,0.0,0.0]);
    camera.setElevation(-40);
    camera.setAzimuth(-30);
    camera.hookRenderer = render;
    
    
    var canvas  = document.getElementById('canvas-element-id');
    
    //Post Process
    post = new PostProcess(canvas, "raytrace-fs");
    
    //Creates and sets up the mouse and keyboard interactor
    interactor = new CameraInteractor(camera, canvas);
        
    //Scene Transforms
    transforms = new SceneTransforms(camera);
   
    //init transforms
    transforms.init();
}

/**
* Loads the scene
*/
function load(){

}

function render(){
    gl.viewport(0, 0, c_width, c_height);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // Checks to see if the framebuffer needs to be resized to match the canvas
    post.validateSize();
    post.bind();

    //Render the fullscreen quad
    post.draw();
}

/**
* Entry point. This function is invoked when the page is loaded
*/
var app = null;
function runWebGLApp() {
    app = new WebGLApp("canvas-element-id");
    app.configureGLHook = configure;
    app.loadSceneHook   = load;
    app.drawSceneHook   = render;
    app.run();
}
</script>
</head>

<body onLoad='runWebGLApp()'>
<div id='top'>
<h1>WebGL Beginner's Guide - Chapter 10</h1>
<h2 id='title-id'>Raytracing</h2>

<div id='logo-packt'><img src='packt.gif'/></div>
<p></p>
</div>

<div id='contents'>
<div id='canvasContainer'>
<canvas id='canvas-element-id' width='480' height='400'>
Your browser does not support the HTML5 canvas element.
</canvas>
</div>
</div>

<div id='bottom'>

</div>
<script> 

</script>
<script>cview.run(cview.MODE_VIEW,false,470);</script>
</body>
</html>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.