summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-07 22:15:42 +0000
committerluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-07 22:15:42 +0000
commitfebe2b6bfa46f46197c9fd619382f169abfe45f8 (patch)
tree9259f62eebe464f7bd8bc42b24a939760bcb8257 /o3d
parent6e10b72ac081588661dd667ec8e156149c24b96d (diff)
downloadchromium_src-febe2b6bfa46f46197c9fd619382f169abfe45f8.zip
chromium_src-febe2b6bfa46f46197c9fd619382f169abfe45f8.tar.gz
chromium_src-febe2b6bfa46f46197c9fd619382f169abfe45f8.tar.bz2
Converted four more demo files to o3d-webgl: juggler, sobel, julia and texturesamplers.
Review URL: http://codereview.chromium.org/2690002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49101 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/samples/o3d-webgl-samples/juggler.html453
-rw-r--r--o3d/samples/o3d-webgl-samples/julia.html285
-rw-r--r--o3d/samples/o3d-webgl-samples/sobel.html339
-rw-r--r--o3d/samples/o3d-webgl-samples/texturesamplers.html274
4 files changed, 1351 insertions, 0 deletions
diff --git a/o3d/samples/o3d-webgl-samples/juggler.html b/o3d/samples/o3d-webgl-samples/juggler.html
new file mode 100644
index 0000000..133e6c8
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/juggler.html
@@ -0,0 +1,453 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+O3D Juggler
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html style="width: 100%; height: 100%;">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+ Juggler Shader
+</title>
+
+<script type="text/javascript" src="../o3d-webgl/base.js"></script>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<script type="text/javascript" id="o3dscript">
+o3djs.base.o3d = o3d;
+o3djs.require('o3djs.webgl');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+
+// Events
+// Run the init() function once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload = unload;
+// global variables
+var g_o3d;
+var g_math;
+var g_client;
+var g_o3dElement;
+var g_viewInfo;
+var g_pack;
+var g_o3dWidth = -1;
+var g_o3dHeight = -1;
+var g_transform;
+var g_clock = 0.0;
+var g_timeMult = 1; // amount to multiply elapsed time by.
+ // Used to make the animation run faster or slower.
+var g_finished = false; // for selenium testing
+var g_thetaParam;
+var g_numParam;
+var g_numBalls; // Must be either 3, 5, 7, or 9 for now.
+var g_speedScale; // Used to make higher numbers of balls animate faster.
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D, loads the effect, and creates the square.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initialize global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Create a g_pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ // Create the render graph for a view.
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_client.renderGraphRoot,
+ [0, 0, 0, 1]);
+
+ var effect = g_pack.createObject('Effect');
+ effect.loadFromFXString(document.getElementById('shader').value);
+
+ // Create a Material for the effect.
+ var myMaterial = g_pack.createObject('Material');
+
+ // Apply our effect to this material.
+ myMaterial.effect = effect;
+
+ // Set the material's drawList for opaque objects.
+ myMaterial.drawList = g_viewInfo.performanceDrawList;
+
+ // Create the params the effect needs on the material.
+ effect.createUniformParameters(myMaterial);
+
+ // Create a square.
+ var myShape = o3djs.primitives.createPlane(g_pack, myMaterial,
+ 1, 1, 1, 1);
+
+ // Set up the individual parameters in our effect file.
+ g_thetaParam = myMaterial.getParam('theta');
+ g_thetaParam.value = 0.0;
+ g_numParam = myMaterial.getParam('num');
+ updateNum();
+
+ // Set the position of the camera.
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [0, 1, 0], //eye
+ [0, 0, 0], //target
+ [0, 0, -1]); //up
+
+ // Generate the projection matrix based
+ // on the g_o3d plugin size by calling resize().
+ resize();
+
+ // Now attach the square to the root of the transform graph.
+ g_client.root.addShape(myShape);
+
+ toggleRenderCallback();
+
+ g_finished = true; // for selenium testing.
+}
+
+function updateNum() {
+ var group = document.the_form.radio_group;
+ for (var i = 0; i < group.length; ++i) {
+ if (group[i].checked) {
+ setNumBalls(parseInt(group[i].value));
+ }
+ }
+}
+
+function toggleRenderCallback() {
+ var box = document.the_form.check_box;
+ if (box.checked) {
+ g_client.setRenderCallback(onrender);
+ } else {
+ g_client.clearRenderCallback();
+ }
+}
+
+function setNumBalls(num) {
+ g_numBalls = num;
+ g_numParam.value = g_numBalls;
+ g_speedScale = Math.sqrt(g_numBalls) * 5;
+}
+
+function onrender(render_event) {
+ g_clock += render_event.elapsedTime * g_timeMult;
+ g_thetaParam.value = g_clock * g_speedScale;
+
+ // If we don't check the size of the client area every frame we don't get a
+ // chance to adjust the perspective matrix fast enough to keep up with the
+ // browser resizing us, so onrender must call resize.
+ resize();
+}
+
+
+// Generates the projection matrix based on the size of the g_o3d plugin
+// and calculates the view-projection matrix.
+function resize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+
+ if (newWidth != g_o3dWidth || newHeight != g_o3dHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+
+ // Determine what the size of the rendered square within the client should
+ // be in pixels.
+ var side = g_o3dWidth < g_o3dHeight ?
+ g_o3dWidth : g_o3dHeight;
+
+ // Convert to the region of world space that must be enclosed by the
+ // orthographic projection.
+ var worldSize = g_math.divVectorScalar([g_o3dWidth, g_o3dHeight], side);
+
+ // Find a projection matrix to transform from world space to screen space.
+ g_viewInfo.drawContext.projection = o3djs.math.matrix4.orthographic(
+ -0.5 * worldSize[0], 0.5 * worldSize[0],
+ -0.5 * worldSize[1], 0.5 * worldSize[1],
+ 0.5, 1.5);
+ }
+}
+
+/**
+ * Removes any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body style="width: 95%; height: 95%;">
+<table style="width: 100%; height: 100%;">
+ <tr>
+ <td>
+ <h1>Juggler</h1>
+ <p>
+ This sample displays a juggling pattern computed entirely in a shader.
+ <form name="the_form">
+ <input type="radio" name="radio_group" value="3"
+ onclick=updateNum()>3 Balls
+ <input type="radio" name="radio_group" value="5"
+ onclick=updateNum()>5 Balls
+ <input type="radio" name="radio_group" value="7"
+ onclick=updateNum()>7 Balls
+ <input type="radio" name="radio_group" value="9"
+ onclick=updateNum()>9 Balls
+ <input type="radio" name="radio_group" value="11" checked
+ onclick=updateNum()>11 Balls
+ <input type="radio" name="radio_group" value="13"
+ onclick=updateNum()>13 Balls
+ <input type="radio" name="radio_group" value="15"
+ onclick=updateNum()>15 Balls
+ <input type="radio" name="radio_group" value="17"
+ onclick=updateNum()>17 Balls
+ <input type="checkbox" name="check_box" checked
+ onclick=toggleRenderCallback()>Animate
+ </form>
+ </p>
+ <table id="container" style="width: 100%; height: 80%;">
+ <tr>
+ <td height="100%">
+ <!-- Start of g_o3d plugin -->
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ <!-- End of g_o3d plugin -->
+ </td>
+ </tr>
+ </table>
+ <!-- a simple way to get a multiline string -->
+ <textarea id="shader" name="shader" cols="80" rows="20"
+ style="display: none;">
+// The 4x4 world view projection matrix.
+uniform mat4 worldViewProjection;
+
+// input parameters for our vertex shader
+attribute vec4 position;
+attribute vec2 texCoord0;
+
+// input parameters for our pixel shader
+varying vec2 v_texCoord;
+
+/**
+ * vertexShaderMain - our vertex shader for the juggling texture
+ */
+void main() {
+ gl_Position = worldViewProjection * position;
+ v_texCoord = 4.0 * (texCoord0 - vec2(0.5, 0.5));
+}
+
+// #o3d SplitMarker
+
+varying vec2 v_texCoord;
+
+uniform float theta;
+uniform float num;
+
+float length_2(vec2 v) {
+ return dot(v, v);
+}
+
+// Draw the balls in a single arc.
+// Returns 1 if the pixel is within a ball, 0 if it isn't, and a value in
+// between for pixels right on the edge, for antialiasing.
+float drawBallsInArc(float pi,
+ vec4 offset,
+ vec2 source_hand,
+ vec2 dest_hand,
+ float height_factor,
+ float baseline,
+ float ball_radius_2,
+ float hand_throw_offset,
+ vec2 Z,
+ float threshold) {
+ // Map theta from its current range of [0, 2 * num * pi) onto [0, (num - 1))
+ // by scaling, adding offset, and modding, then map that to [0, 1) by scaling.
+ // The first mapping tells us where in the repeating cycle we are, and the
+ // second mapping simplifies the calculation of the parabola.
+
+ // The vector offset is used to distinguish between balls in the same arc, but
+ // out of phase. At the beginning of this function, all the operations are
+ // vectorized to save instructions; we get to calculate 4 ball positions for
+ // the price of 1.
+
+ // The reason for the (num - 1) in the expression below is that with num
+ // balls, each ball spends (num - 1) beats in the air, then one in the hand.
+ // So (num - 1) is the length of time a parabola takes.
+
+ vec4 time = mod(theta / pi + offset, (num - 1.0)) / (num - 1.0);
+ float dx = dest_hand.x - source_hand.x;
+ vec4 x = time * dx + source_hand.x - hand_throw_offset;
+ vec4 y = time * (1.0 - time);
+ y = y * height_factor + baseline;
+ vec4 ZX = vec4(Z.x);
+ vec4 ZY = vec4(Z.y);
+ vec4 len_2 = (ZX - x) * (ZX - x) + (ZY - y) * (ZY - y);
+
+ // This antialiasing fuzzes the balls just a bit larger than they would
+ // otherwise be.
+ vec4 temp = clamp((len_2 - ball_radius_2) / threshold, 0.0, 1.0);
+
+ // One minus the product of all entries in temp.
+ temp.xy = temp.xy * temp.zw;
+ return 1.0 - temp.x * temp.y;
+}
+
+vec4 drawAirborneBalls(float pi,
+ vec4 offset,
+ vec2 right_hand,
+ vec2 left_hand,
+ float height_factor,
+ float baseline,
+ float ball_radius_2,
+ float hand_swing_radius,
+ vec2 Z,
+ float threshold) {
+ float value =
+ // balls going right to left
+ (drawBallsInArc(pi, offset, right_hand, left_hand, height_factor,
+ baseline, ball_radius_2, hand_swing_radius, Z, threshold) +
+ // balls going left to right
+ drawBallsInArc(pi, offset + 1.0, left_hand, right_hand, height_factor,
+ baseline, ball_radius_2, -hand_swing_radius, Z, threshold));
+ return vec4(value, value, value, value);
+}
+
+
+/**
+ * pixelShaderMain - pixel shader
+ */
+
+void main() {
+ float pi = 3.14159265;
+ float baseline = -1.4;
+ vec2 right_hand = vec2(0.8, baseline);
+ vec2 left_hand = vec2(-0.8, baseline);
+ float hand_swing_radius = 0.25;
+ float hand_radius = 0.15;
+ float hand_radius_2 = hand_radius * hand_radius;
+ float ball_radius = 0.08;
+ float ball_radius_2 = ball_radius * ball_radius;
+
+ vec4 right_hand_color = vec4(1, 0, 0, 1);
+ vec4 left_hand_color = vec4(0, 0, 1, 1);
+ vec4 background_color = vec4(0, 0, 0, 0);
+
+ float threshold = 0.002; // Used in clamp for antialiasing.
+
+ float height_factor = num * 0.75;
+
+ vec2 Z = v_texCoord;
+
+ // Coerce to the range [0, 2 * Pi * num].
+ vec2 r_h = hand_swing_radius * vec2(-cos(theta), sin(theta)) + right_hand;
+ vec2 l_h = hand_swing_radius * vec2(-cos(theta), -sin(theta)) + left_hand;
+
+ // Initialize color of pixel to background_color. Background color has an
+ // alpha of 0. Color of objects each have alpha 1, so multiplying by
+ // (1-alpha) before adding the color ensures that nothing gets overdrawn.
+ // It's kind of like a rudimentary z-buffer.
+ vec4 result = background_color;
+
+ // Draw the hands. The antialiasing here fuzzes the hands just a little bit
+ // smaller than they would otherwise be. That's the opposite of what we do
+ // for the balls, just because it happens to be cheaper here to do smaller and
+ // cheaper in drawBallsInArc to do larger.
+ result +=
+ clamp((hand_radius_2 - length_2(Z - r_h)) / threshold, 0.0, 1.0) *
+ (Z.y < r_h.y ? 1.0 : 0.0) * right_hand_color +
+ clamp((hand_radius_2 - length_2(Z - l_h)) / threshold, 0.0, 1.0) *
+ (Z.y < l_h.y ? 1.0 : 0.0) * left_hand_color;
+ // Draw the ball in the hand. There is always a ball in exactly one hand, and
+ // which hand that is alternates.
+ vec2 hand;
+ if (mod(floor(theta / pi), 2.0) > 0.5) {
+ hand = r_h;
+ } else {
+ hand = l_h;
+ }
+
+ // The antialiasing here fuzzes the balls just a bit bigger than they would
+ // otherwise be. This is more work than making them smaller [the extra
+ // subtraction in the "1 - clamp..." below], but inverting it in
+ // drawBallsInArc would be more expensive, and they have to match so that the
+ // balls are all the same size.
+ result += (1.0 - result.a) *
+ (1.0 - clamp((length_2(Z - hand) - ball_radius_2) / threshold, 0.0, 1.0));
+
+ // Draw airborne balls.
+ vec4 offset = vec4(0, 2, 4, 6);
+ result += (1.0 - result.a) * drawAirborneBalls(pi,
+ offset,
+ right_hand,
+ left_hand,
+ height_factor,
+ baseline,
+ ball_radius_2,
+ hand_swing_radius,
+ Z,
+ threshold);
+
+ // For each up-to-4 pairs of balls you want to add, increment offset by
+ // (8, 8, 8, 8) and call drawAirborneBalls again.
+ offset += 8.0;
+ result += (1.0 - result.a) * drawAirborneBalls(pi,
+ offset,
+ right_hand,
+ left_hand,
+ height_factor,
+ baseline,
+ ball_radius_2,
+ hand_swing_radius,
+ Z,
+ threshold);
+
+ gl_FragColor = result;
+}
+
+// #o3d MatrixLoadOrder RowMajor
+ </textarea>
+ </td>
+ </tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/o3d-webgl-samples/julia.html b/o3d/samples/o3d-webgl-samples/julia.html
new file mode 100644
index 0000000..30dbaf4
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/julia.html
@@ -0,0 +1,285 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+O3D Julia Set
+
+This sample draws an animated julia set in real time using
+the pixel shader for the computation.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html style="width: 100%; height: 100%;">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Julia Set Pixel Shader
+</title>
+
+<script type="text/javascript" src="../o3d-webgl/base.js"></script>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<script type="text/javascript" id="o3dscript">
+o3djs.base.o3d = o3d;
+o3djs.require('o3djs.webgl');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+
+// Events
+// Run the init() function once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload = unload;
+// global variables
+var g_o3d;
+var g_math;
+var g_client;
+var g_o3dElement;
+var g_viewInfo;
+var g_pack;
+var g_o3dWidth = -1;
+var g_o3dHeight = -1;
+var g_clock = 0.0;
+var g_timeMult = 1;
+var g_finished = false; // for selenium testing
+var g_seedParam;
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes o3d, loads the effect, and creates the square.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initialize global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Create a g_pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ // Create the render graph for a view.
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_client.renderGraphRoot,
+ [0, 0, 0, 1]);
+
+ // Load shader code from DOM and use it to build the effect.
+ var effect = g_pack.createObject('Effect');
+ effect.loadFromFXString(document.getElementById('shader').value);
+
+ // Create a Material for the effect.
+ var myMaterial = g_pack.createObject('Material');
+
+ // Apply our effect to this material.
+ myMaterial.effect = effect;
+
+ // Set the material's drawList for opaque objects.
+ myMaterial.drawList = g_viewInfo.performanceDrawList;
+
+ // create the parameters the effect needs to the material.
+ effect.createUniformParameters(myMaterial);
+
+ // Create a square.
+ var myShape = o3djs.primitives.createPlane(g_pack, myMaterial, 1, 1, 1, 1);
+
+ // Initialize effect parameters to something reasonable
+ g_seedParam = myMaterial.getParam('seed');
+ g_seedParam.value = [0.2, 0.5];
+
+ // Put the camera somewhere where it has a good view of that square.
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [0, 1, 0], //eye
+ [0, 0, 0], //target
+ [0, 0, -1]); //up
+
+ // Generate the projection matrix based
+ // on the g_o3d plugin size by calling resize().
+ resize();
+
+ // Now attach the square to the root of the transform graph.
+ g_client.root.addShape(myShape);
+
+ g_client.setRenderCallback(onrender);
+
+ g_finished = true; // for selenium testing.
+}
+
+
+/**
+ * Render callback. Walks the seed of the Julia set through
+ * a parametric path in the complex plane that stays
+ * in the neighborhood of the Mandelbrot set.
+ */
+function onrender(render_event) {
+ g_clock += render_event.elapsedTime * g_timeMult;
+
+ var t = 0.1 * g_clock;
+ var x = 0.6 * Math.cos(3.0 * t) - 0.3;
+ var y = (0.5 * x + 1.7)*(0.2 * Math.sin(7 * t));
+
+ g_seedParam.value = [x, y];
+
+ resize();
+}
+
+
+/**
+ * Generates the projection matrix based on the size of the o3d plugin and
+ * calculates the view-projection matrix.
+ */
+function resize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+
+ if (newWidth != g_o3dWidth || newHeight != g_o3dHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+
+ // Determine what the size of the rendered square within the client should
+ // be in pixels.
+ var side = g_o3dWidth < g_o3dHeight ?
+ g_o3dWidth : g_o3dHeight;
+
+ // Convert to the region of world space that must be enclosed by the
+ // orthographic projection.
+ var worldSize = g_math.divVectorScalar([g_o3dWidth, g_o3dHeight], side);
+
+ // Find a projection matrix to transform from world space to screen space.
+ g_viewInfo.drawContext.projection = g_math.matrix4.orthographic(
+ -0.5 * worldSize[0], 0.5 * worldSize[0],
+ -0.5 * worldSize[1], 0.5 * worldSize[1],
+ 0.5, 1.5);
+ }
+}
+
+
+/**
+ * Removes any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+
+
+</script>
+</head>
+<body style="width: 100%; height: 100%;">
+<table style="width: 100%; height: 100%;">
+ <tr>
+ <td>
+ <h1>Julia Set</h1>
+ <p>
+ This sample draws an animated julia set in real time using
+ the pixel shader for the computation.
+ </p>
+ <table id="container" style="width: 100%; height: 80%;">
+ <tr>
+ <td height="100%">
+ <!-- Start of g_o3d plugin -->
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ <!-- End of g_o3d plugin -->
+ </td>
+ </tr>
+ </table>
+ <!-- a simple way to get a multiline string -->
+ <textarea id="shader" name="shader" cols="80" rows="20"
+ style="display: none;">
+// The 4x4 world view projection matrix.
+uniform mat4 worldViewProjection;
+
+// input parameters for our vertex shader
+attribute vec4 position;
+attribute vec2 texCoord0;
+
+// input parameters for our pixel shader
+varying vec2 texCoord;
+
+/**
+ * vertexShaderMain - Multiplies position by world-view-projection matrix, and
+ * passes on texture coordinates scaled to put the origin in the center of the
+ * quad and reveal a nicely sized portion of the plane to show the julia set.
+ */
+void main() {
+ gl_Position = worldViewProjection * position;
+ texCoord = 4.0 * (texCoord0 - vec2(0.5, 0.5));
+}
+
+
+// #o3d SplitMarker
+
+varying vec2 texCoord;
+
+// The seed for the julia set (c in the expression z(n+1) = z(n)^2+c).
+uniform vec2 seed;
+
+/**
+ * pixelShaderMain - Calculates the color of the pixel by iterating on the
+ * formula z = z*z + seed. After some number of iterations, the magnitude of z
+ * determines the color.
+ */
+void main() {
+ vec2 Z = texCoord;
+
+ // Number of iterations hardcoded here. The more iterations, the crisper the
+ // image.
+ for(int i = 0; i < 10; ++i) {
+ Z = vec2(Z.x * Z.x - Z.y * Z.y, 2.0 * Z.x * Z.y) + seed;
+
+ // Some graphics cards and some software renderers don't appreciate large
+ // floating point values, so we clamp to prevent Z from getting that big.
+ if (i > 7) {
+ Z = clamp(Z, -25.0, 25.0);
+ }
+ }
+
+ gl_FragColor = (1.0 - length(Z)) * vec4(0.5, 1, 2, 1);
+}
+// #o3d MatrixLoadOrder RowMajor
+ </textarea>
+ </td>
+ </tr>
+</table>
+</body>
+</html>
+
+
diff --git a/o3d/samples/o3d-webgl-samples/sobel.html b/o3d/samples/o3d-webgl-samples/sobel.html
new file mode 100644
index 0000000..b7105d3
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/sobel.html
@@ -0,0 +1,339 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+This sample shows how to create a Sobel edge-detect image processing shader,
+using render targets.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+O3D: Sobel Shader Sample
+</title>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3d-webgl/base.js"></script>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+<script type="text/javascript" id="o3dscript">
+o3djs.base.o3d = o3d;
+o3djs.require('o3djs.webgl');
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.pack');
+o3djs.require('o3djs.camera');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.scene');
+
+// Events
+// init() once the page has finished loading.
+window.onload = init;
+window.onunload = uninit;
+
+// constants.
+var RENDER_TARGET_WIDTH = 512;
+var RENDER_TARGET_HEIGHT = 512;
+
+// global variables
+var g_o3d;
+var g_client;
+var g_math;
+var g_pack;
+var g_teapotRoot;
+var g_renderGraphRoot;
+var g_clock = 0;
+var g_timeMult = 1;
+var g_finished = false; // for selenium testing
+
+/**
+ * Loads a scene into the transform graph, and prepares its elements for
+ * insertion into the render graph.
+ * @param {!o3d.Pack} pack Pack to load scene into.
+ * @param {string} fileName filename of the scene.
+ * @param {!o3d.Transform} parent parent node in the transform graph to
+ * which to load the scene into.
+ * @param {!o3djs.rendergraph.ViewInfo} viewInfo who's view and projection will
+ * be set from the scene after it's loaded.
+ */
+function loadScene(pack, fileName, parent, viewInfo) {
+ // Get our full path to the scene
+ var scenePath = o3djs.util.getCurrentURI() + fileName;
+
+ // Load the scene given the full path, and call the callback function
+ // when its done loading.
+ o3djs.scene.loadScene(g_client, pack, parent, scenePath, callback);
+
+ /**
+ * Our callback is called once the scene has been loaded into memory
+ * from the web or locally.
+ * @param {!o3d.Pack} pack The pack that was passed in above.
+ * @param {!o3d.Transform} parent The parent that was passed in above.
+ * @param {*} exception null if loading succeeded.
+ */
+ function callback(pack, parent, exception) {
+ if (exception) {
+ alert('Could not load: ' + fileName + '\n' + exception);
+ return;
+ }
+ // Get a CameraInfo (an object with a view and projection matrix)
+ // using our javascript library function
+ var cameraInfo = o3djs.camera.getViewAndProjectionFromCameras(
+ parent,
+ RENDER_TARGET_WIDTH,
+ RENDER_TARGET_HEIGHT);
+
+ // Copy the view and projection to the passed in viewInfo structure..
+ viewInfo.drawContext.view = cameraInfo.view;
+ viewInfo.drawContext.projection = cameraInfo.projection;
+
+ // Generate draw elements and setup material draw lists.
+ o3djs.pack.preparePack(pack, viewInfo);
+
+ g_finished = true; // for selenium testing.
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and loads the scene into the transform graph.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ var o3d = clientElements[0];
+ g_o3d = o3d.o3d;
+ g_math = o3djs.math;
+ g_client = o3d.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ // Create the texture required for the color render-target.
+ var texture = g_pack.createTexture2D(RENDER_TARGET_WIDTH,
+ RENDER_TARGET_HEIGHT,
+ g_o3d.Texture.XRGB8, 1, true);
+
+ g_teapotRoot = g_pack.createObject('Transform');
+
+ var renderGraphRoot = g_client.renderGraphRoot;
+
+ var renderSurfaceSet = createRenderSurfaceSet(texture);
+
+ // Create the render graph for the teapot view, drawing the teapot into
+ // texture (via renderSurfaceSet).
+ var teapotViewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_teapotRoot,
+ renderSurfaceSet,
+ [1, 1, 1, 1]);
+
+ var renderNode = createSobelPass(texture, g_client.renderGraphRoot);
+
+ // Load the scene into the transform graph as a child g_teapotRoot
+ loadScene(g_pack, '../assets/teapot/scene.json', g_teapotRoot, teapotViewInfo);
+
+ // Set a render callback.
+ g_client.setRenderCallback(onRender);
+}
+
+function createSobelMaterial(viewInfo, kernelSize) {
+ var convFXString = document.getElementById('convFX').value;
+ var convEffect = g_pack.createObject('Effect');
+ convEffect.loadFromFXString(convFXString);
+
+ var convMaterial = g_pack.createObject('Material');
+ convMaterial.drawList = viewInfo.performanceDrawList;
+ convMaterial.effect = convEffect;
+ convEffect.createUniformParameters(convMaterial);
+ return convMaterial;
+}
+
+function createRenderSurfaceSet(texture) {
+ var renderSurface = texture.getRenderSurface(0);
+
+ // Create the depth-stencil buffer required when rendering this pass.
+ var depthSurface = g_pack.createDepthStencilSurface(RENDER_TARGET_WIDTH,
+ RENDER_TARGET_HEIGHT);
+
+ var renderSurfaceSet = g_pack.createObject('RenderSurfaceSet');
+ renderSurfaceSet.renderSurface = renderSurface;
+ renderSurfaceSet.renderDepthStencilSurface = depthSurface;
+ renderSurfaceSet.parent = g_client.renderGraphRoot;
+ return renderSurfaceSet;
+}
+
+function createSobelPass(srcTexture, renderGraphRoot) {
+ // Create a root Transform for the image processing scene.
+ var root = g_pack.createObject('Transform');
+
+ // Create a basic view for the image processing scene.
+ var viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ root,
+ renderGraphRoot,
+ [1, 1, 1, 1]);
+
+ var material = createSobelMaterial(viewInfo);
+ var quadShape = o3djs.primitives.createPlane(g_pack,
+ material,
+ 2.0,
+ 2.0,
+ 1,
+ 1);
+
+ // Attach the quad to the image processing scene.
+ root.addShape(quadShape);
+
+ // Rotate the view so we're looking at the XZ plane (where our quad is)
+ // Point the camera along the -Y axis
+ var target = [0, -1, 0];
+ // Put the camera at the origin.
+ var eye = [0, 0, 0];
+ // Define the up-vector as +Z
+ var up = [0, 0, 1];
+ viewInfo.drawContext.view = g_math.matrix4.lookAt(eye, target, up);
+
+ // Create an orthographic projection.
+ viewInfo.drawContext.projection = g_math.matrix4.orthographic(
+ -1, 1, -1, 1, -1, 1);
+
+ // Generate draw elements and setup material draw lists for the
+ // image processing scene.
+ o3djs.pack.preparePack(g_pack, viewInfo);
+
+ setSobelParameters(material, srcTexture);
+ return renderGraphRoot;
+}
+
+function setSobelParameters(material, texture) {
+ var imageParam = material.getParam('image');
+ var imageIncrement = material.getParam('imageIncrement');
+ var sampler = g_pack.createObject('Sampler');
+ sampler.texture = texture;
+ sampler.addressModeU = g_o3d.Sampler.CLAMP;
+ sampler.addressModeV = g_o3d.Sampler.CLAMP;
+ sampler.minFilter = g_o3d.Sampler.POINT;
+ sampler.magFilter = g_o3d.Sampler.POINT;
+ sampler.mipFilter = g_o3d.Sampler.NONE;
+ imageParam.value = sampler;
+ imageIncrement.value = [1.0 / texture.width, 1.0 / texture.height];
+}
+
+/**
+ * Called every frame.
+ * @param {o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+ g_clock += elapsedTime * g_timeMult;
+
+ g_teapotRoot.identity();
+ g_teapotRoot.rotateX(g_clock);
+ g_teapotRoot.rotateY(g_clock * 1.3);
+}
+
+/**
+ * Cleanup before exiting.
+ */
+function uninit() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<h1>Sobel Edge Detection Shader Example</h1>
+<br/>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 512px; height: 512px;"></div>
+<!-- End of O3D plugin -->
+<!--
+ We embed the code for our effect inside this hidden textarea.
+ Effects contain the functions that define
+ the vertex and pixel shaders used by our shape.
+-->
+<!-- Don't render the textarea -->
+<div style="display:none">
+<textarea id="convFX" name="convFX" cols="80" rows="20">
+uniform mat4 worldViewProjection;
+
+attribute vec4 position;
+attribute vec2 texCoord0;
+
+varying vec2 v_imageCoord;
+
+void main() {
+ gl_Position = worldViewProjection * position;
+ v_imageCoord = texCoord0;
+}
+
+// #o3d SplitMarker
+uniform sampler2D image;
+uniform vec2 imageIncrement;
+
+varying vec2 v_imageCoord;
+
+float lum(vec4 c) {
+ return dot(c.xyz, vec3(0.3, 0.59, 0.11));
+}
+
+void main() {
+ vec2 imageCoord = v_imageCoord;
+ float t00 = lum(texture2D(image, imageCoord + imageIncrement * vec2(-1, -1)));
+ float t10 = lum(texture2D(image, imageCoord + imageIncrement * vec2( 0, -1)));
+ float t20 = lum(texture2D(image, imageCoord + imageIncrement * vec2( 1, -1)));
+ float t01 = lum(texture2D(image, imageCoord + imageIncrement * vec2(-1, 0)));
+ float t21 = lum(texture2D(image, imageCoord + imageIncrement * vec2( 1, 0)));
+ float t02 = lum(texture2D(image, imageCoord + imageIncrement * vec2(-1, 1)));
+ float t12 = lum(texture2D(image, imageCoord + imageIncrement * vec2( 0, 1)));
+ float t22 = lum(texture2D(image, imageCoord + imageIncrement * vec2( 1, 1)));
+ vec2 grad;
+ grad.x = t00 + 2.0 * t01 + t02 - t20 - 2.0 * t21 - t22;
+ grad.y = t00 + 2.0 * t10 + t20 - t02 - 2.0 * t12 - t22;
+ float len = length(grad);
+ gl_FragColor = vec4(len, len, len, 1.0);
+}
+
+// #o3d MatrixLoadOrder RowMajor
+</textarea>
+</div>
+</body>
+
+</html>
diff --git a/o3d/samples/o3d-webgl-samples/texturesamplers.html b/o3d/samples/o3d-webgl-samples/texturesamplers.html
new file mode 100644
index 0000000..13ef9c9
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/texturesamplers.html
@@ -0,0 +1,274 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+O3D Texture Samplers example.
+
+Demonstrates how to create samplers and set their various states.
+-->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Texture Samplers
+</title>
+<script type="text/javascript" src="../o3d-webgl/base.js"></script>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+<script type="text/javascript" id="o3dscript">
+o3djs.base.o3d = o3d;
+o3djs.require('o3djs.webgl');
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.event');
+o3djs.require('o3djs.io');
+
+// Events
+// Run the init() once the page has finished loading.
+window.onload = init;
+
+// global variables
+var g_o3d;
+var g_math;
+var g_client;
+var g_pack;
+var g_viewInfo;
+var g_eye;
+var g_target;
+var g_up;
+var g_finished = false; // for selenium testing
+
+function scrollMe(e) {
+ g_eye = g_math.mulScalarVector((e.deltaY < 0 ? 11 : 13) / 12, g_eye);
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ // Prevents event from reaching up to the window, e.g. so page will not scroll
+ o3djs.event.cancel(e);
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D, loads the effect, and draws the quads.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initialize global variables and libraries.
+ var o3dElement = clientElements[0];
+ g_o3d = o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = o3dElement.client;
+
+ // Create a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ // Create the render graph for a view.
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_client.renderGraphRoot);
+
+ // Create our projection matrix, with a vertical field of view of 45 degrees
+ // a near clipping plane of 0.1 and far clipping plane of 100.
+ var proj_matrix = g_math.matrix4.perspective(
+ g_math.degToRad(45),
+ g_client.width / g_client.height,
+ 0.1,
+ 100);
+
+ // Create the view matrix which tells the camera which way to point to.
+ g_eye = [0, 4, 0];
+ g_target = [0, 0, 0];
+ g_up = [0, 0, -1];
+ var view_matrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+
+ g_viewInfo.drawContext.view = view_matrix;
+ g_viewInfo.drawContext.projection = proj_matrix;
+
+ var samplers = [];
+ var transforms = [];
+
+ for (var xx = 0; xx < 3; xx++) {
+ for (var yy = 0; yy < 2; yy++) {
+ var index = yy * 3 + xx;
+
+ //Create effect for shaders.
+ var effect = g_pack.createObject('Effect');
+ var vertexShaderString = document.getElementById('vshader').value;
+ var pixelShaderString = document.getElementById('pshader').value;
+ effect.loadVertexShaderFromString(vertexShaderString);
+ effect.loadPixelShaderFromString(pixelShaderString);
+
+ // Create a new Material for the quad.
+ var material = g_pack.createObject('Material');
+ material.drawList = g_viewInfo.performanceDrawList;
+ material.effect = effect;
+
+ effect.createUniformParameters(material);
+
+ // Create a quad and position it.
+ var verts = o3djs.primitives.createPlaneVertices(1, 1, 1, 1);
+ var texCoordStream = verts.findStream(g_o3d.Stream.TEXCOORD, 0);
+ // make the UVs go from 0 to 2 instead of 0 to 1
+ for (var v = 0; v < texCoordStream.elements.length; ++v) {
+ texCoordStream.elements[v] *= 2;
+ }
+ var shape = verts.createShape(g_pack, material);
+
+ // Make a transform for each quad.
+ var transform = g_pack.createObject('Transform');
+ transform.translate([(xx - 1) * 1.2, 0, (0.5 - yy) * -1.2]);
+ transform.addShape(shape);
+
+
+ // Get the sampler on the sampler param.
+ var sampler = g_pack.createObject('Sampler');
+ samplers[index] = sampler;
+ transforms[index] = transform;
+ material.getParam('texSampler').value = sampler;
+ }
+ }
+
+ // Set the sampler states on each sampler.
+ // Looking at the generated image, the samplers correspond to the
+ // following quads:
+ // [0] [1] [2]
+ // [3] [4] [5]
+ // Sampler states not specified assume their default values which are:
+ // addressModeU = Sampler.WRAP
+ // addressModeV = Sampler.WRAP
+ // minFilter = Sampler.LINEAR
+ // magFilter = Sampler.LINEAR
+ // mipFilter = Sampler.POINT
+ // borderColor = Float4(0, 0, 0, 0)
+ // maxAnisotropy = 1
+
+ // Rotates quad and uses anisotropic filtering.
+ transforms[1].rotateZ(-Math.PI / 2.5);
+ samplers[1].addressModeU = g_o3d.Sampler.WRAP;
+ samplers[1].addressModeV = g_o3d.Sampler.WRAP;
+ samplers[1].minFilter = g_o3d.Sampler.ANISOTROPIC;
+ samplers[1].maxAnisotropy = 4;
+
+ // Uses BORDER addressing mode with a red border.
+ samplers[2].addressModeU = g_o3d.Sampler.BORDER;
+ samplers[2].addressModeV = g_o3d.Sampler.BORDER;
+ samplers[2].borderColor = [1, 0, 0, 1];
+
+ // Uses POINT sampling for minification.
+ samplers[3].addressModeU = g_o3d.Sampler.WRAP;
+ samplers[3].addressModeV = g_o3d.Sampler.WRAP;
+ samplers[3].minFilter = g_o3d.Sampler.POINT;
+
+ // Rotates quad and uses default (linear) filtering.
+ // Compare results to quad #1.
+ transforms[4].rotateZ(-Math.PI / 2.5);
+ samplers[4].addressModeU = g_o3d.Sampler.WRAP;
+ samplers[4].addressModeV = g_o3d.Sampler.WRAP;
+ samplers[4].minFilter = g_o3d.Sampler.LINEAR;
+ samplers[4].magFilter = g_o3d.Sampler.LINEAR;
+
+ // Uses MIRROR addressing mode to mirror the texture on both axes.
+ samplers[5].addressModeU = g_o3d.Sampler.MIRROR;
+ samplers[5].addressModeV = g_o3d.Sampler.MIRROR;
+
+ // Load our texture!
+ var url = o3djs.util.getCurrentURI() + '../assets/texture_b3.jpg';
+ o3djs.io.loadTexture(g_pack, url, function(texture, exception) {
+ if (exception) {
+ alert(exception);
+ } else {
+ // Use the same texture for all the samplers.
+ for (var ii = 0; ii < samplers.length; ii++) {
+ samplers[ii].texture = texture;
+ }
+ // Parent the transforms. We do this here because until the texture
+ // is loaded our quads are not ready to display.
+ for (var ii = 0; ii < transforms.length; ii++) {
+ transforms[ii].parent = g_client.root;
+ }
+ g_finished = true; // for selenium testing.
+ }
+ });
+
+ o3djs.event.addEventListener(o3dElement, 'wheel', scrollMe);
+}
+</script>
+</head>
+<body>
+<h1>Texture Sampler Example</h1>
+This tutorial demonstrates various texture sampler settings.
+<br/>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 700px; height: 600px"></div>
+<p>Scrollwheel To Zoom</p><br/>
+<!-- End of O3D plugin -->
+
+<textarea id="vshader" style="display: none;">
+uniform mat4 worldViewProjection;
+
+// input parameters for our vertex shader
+attribute vec4 position;
+attribute vec2 texCoord0;
+
+// input parameters for our pixel shader
+varying vec2 texCoord;
+
+/**
+ * Our vertex shader
+ */
+void main() {
+ gl_Position = worldViewProjection * position;
+ texCoord = texCoord0;
+}
+</textarea>
+<textarea id="pshader" style="display: none;">
+varying vec2 texCoord;
+uniform sampler2D texSampler;
+
+/* Given the texture coordinates, our pixel shader grabs the corresponding
+ * color from the texture.
+ */
+void main() {
+ gl_FragColor = texture2D(texSampler, texCoord);
+}
+</textarea>
+</body>
+</html>