summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-16 19:15:12 +0000
committerluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-16 19:15:12 +0000
commit56ee0640b54efe07556c0c5d223551e6744273d0 (patch)
tree9e43dc4f4d1b05accc153c77e2d3488c6f58e0e1 /o3d
parent46ce5b568acd801330e52a4e04534d9689990835 (diff)
downloadchromium_src-56ee0640b54efe07556c0c5d223551e6744273d0.zip
chromium_src-56ee0640b54efe07556c0c5d223551e6744273d0.tar.gz
chromium_src-56ee0640b54efe07556c0c5d223551e6744273d0.tar.bz2
o3d-webgl: vertex shader and vertex animation demos.
Review URL: http://codereview.chromium.org/2821003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50006 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/samples/o3d-webgl-samples/vertex-shader-animation.html203
-rw-r--r--o3d/samples/o3d-webgl-samples/vertex-shader.html334
-rw-r--r--o3d/samples/shaders/phong-vertex-anim-glsl.shader100
3 files changed, 637 insertions, 0 deletions
diff --git a/o3d/samples/o3d-webgl-samples/vertex-shader-animation.html b/o3d/samples/o3d-webgl-samples/vertex-shader-animation.html
new file mode 100644
index 0000000..331011c
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/vertex-shader-animation.html
@@ -0,0 +1,203 @@
+<!--
+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 Vertex Shader Animation Example.
+
+Demonstrates using a vertex shader for simple animation. The shader moves the
+vertices in a sin wave based on the parameter "time" and the world position
+of the vertices.
+-->
+
+<!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>
+Vertex Shader Animation
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ }
+</style>
+<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');
+
+// global variables
+var g_o3d;
+var g_o3dElement;
+var g_math;
+var g_client;
+var g_pack;
+var g_viewInfo;
+var g_timeParam;
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ // These are here so that they are visible to both the browser (so
+ // selenium sees them) and the embedded V8 engine.
+ window.g_clock = 0;
+ window.g_timeMult = 1;
+ window.g_finished = false; // for selenium testing.
+
+ // Comment out the line below to run the sample in the browser
+ // JavaScript engine. This may be helpful for debugging.
+ o3djs.util.setMainEngine(o3djs.util.Engine.V8);
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D, loads the effect, and creates the quads.
+ * @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;
+
+ // Set window.g_client as well. Otherwise when the sample runs in
+ // V8, selenium won't be able to find this variable (it can only see
+ // the browser environment).
+ window.g_client = g_client = g_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 a material.
+ var material = o3djs.material.createMaterialFromFile(
+ g_pack,
+ '../shaders/phong-vertex-anim-glsl.shader',
+ g_viewInfo.performanceDrawList);
+
+ // Set the material parameters.
+ material.getParam('lightWorldPos').value = [-40, 100, 0];
+ material.getParam('lightIntensity').value = [1, 1, 1, 1];
+ material.getParam('ambientIntensity').value = [0.1, 0.1, 0.1, 1];
+ material.getParam('ambient').value = [1, 1, 1, 1];
+ material.getParam('diffuse').value = [1, 1, 1, 1];
+ material.getParam('specular').value = [1, 1, 1, 1];
+ material.getParam('shininess').value = 50;
+
+ g_timeParam = material.getParam('time');
+
+ // Create the view matrix which tells the camera which way to point to.
+ var eye = [10, 50, 20];
+ var target = [2, 0, -2];
+ var up = [0, 0, -1];
+ var view_matrix = g_math.matrix4.lookAt(eye, target, up);
+
+ g_viewInfo.drawContext.view = view_matrix;
+
+ var shape = o3djs.primitives.createPlane(g_pack, material,
+ 10, 10, 100, 100);
+ for (var xx = 0; xx < 5; xx++) {
+ for (var yy = 0; yy < 4; yy++) {
+ var index = yy * 3 + xx;
+
+ // Make a transform for each quad.
+ var transform = g_pack.createObject('Transform');
+ transform.translate((xx - 2) * 12, 0, (2 - yy) * -12);
+ transform.addShape(shape);
+ transform.parent = g_client.root;
+ transform.createParam('diffuse', 'ParamFloat4').value = [xx * 0.2,
+ yy * 0.25,
+ 0.5,
+ 1];
+ }
+ }
+
+ // Setup an onrender callback for animation.
+ g_client.setRenderCallback(onrender);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+function updateProjectionMatrix() {
+ // 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.
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45),
+ g_client.width / g_client.height,
+ 0.1,
+ 100);
+}
+
+// spin the camera.
+function onrender(render_event) {
+ // Get the number of seconds since the last render.
+ var elapsedTime = render_event.elapsedTime;
+ // Update g_clock in the browser and cache a V8 copy that can be
+ // accessed efficiently. g_clock must be in the browser for selenium.
+ var clock = window.g_clock + elapsedTime * window.g_timeMult;
+ window.g_clock = clock;
+
+ updateProjectionMatrix();
+
+ g_timeParam.value = clock * 4;
+}
+
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+
+</script>
+</head>
+<body onload="init()" onunload="unload()">
+<h1>Vertex Shader Animation Example</h1>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 100%; height: 80%"></div>
+<!-- End of O3D plugin -->
+</body>
+</html>
diff --git a/o3d/samples/o3d-webgl-samples/vertex-shader.html b/o3d/samples/o3d-webgl-samples/vertex-shader.html
new file mode 100644
index 0000000..526736e
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/vertex-shader.html
@@ -0,0 +1,334 @@
+<!--
+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 Vertex Shader Demo
+
+This sample uses a custom vertex shader to quickly adjust the positions and
+normals of many vertices in a plane to achieve a ripple effect without iterating
+through the vertices in javascript.
+-->
+<!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>
+Vertex 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.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.effect');
+
+// global variables
+var g_o3dElement;
+var g_client;
+var g_o3d;
+var g_math;
+var g_pack;
+var g_viewInfo;
+var g_clockParam;
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ // These are here so that they are visible to both the browser (so
+ // selenium sees them) and the embedded V8 engine.
+ window.g_clock = 0;
+ window.g_timeMult = 1;
+ window.g_finished = false; // for selenium testing.
+
+ // Comment out the line below to run the sample in the browser
+ // JavaScript engine. This may be helpful for debugging.
+ o3djs.util.setMainEngine(o3djs.util.Engine.V8);
+
+ o3djs.webgl.makeClients(initStep2, 'LargeGeometry');
+}
+
+
+/**
+ * Initializes global variables, positions camera, creates the material, and
+ * draws the plane.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Init global variables.
+ initGlobals(clientElements);
+
+ // Set up the view and projection transformations.
+ initContext();
+
+ // Add the shapes to the transform hierarchy.
+ createPlane();
+
+ // Setup render callback.
+ g_client.setRenderCallback(onRender);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+
+/**
+ * Initializes global variables and libraries.
+ * @param {Array} clientElements An array of o3d object elements assumed
+ * to have one entry.
+ */
+function initGlobals(clientElements) {
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+
+ // Set window.g_client as well. Otherwise when the sample runs in
+ // V8, selenium won't be able to find this variable (it can only see
+ // the browser environment).
+ window.g_client = g_client = g_o3dElement.client;
+
+ // Create a pack to manage the objects created.
+ 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);
+}
+
+
+/**
+ * Sets up reasonable view and projection matrices.
+ */
+function initContext() {
+ // Set up a perspective transformation for the projection.
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(30), // 30 degree frustum.
+ g_client.width / g_client.height, // Aspect ratio.
+ 1, // Near plane.
+ 5000); // Far plane.
+
+ // Set up our view transformation to look towards the world origin where the
+ // cube is located.
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [4, 4, 4], // eye
+ [0, 0, 0], // target
+ [0, 1, 0]); // up
+}
+
+
+/**
+ * Creates an effect using the shaders in the textarea in the document, applies
+ * the effect to a new material, binds the uniform parameters of the shader
+ * to parameters of the material, and sets certain parameters: the light and
+ * camera position.
+ * @return {Material} The material.
+ */
+function createMaterial() {
+ // Create a new, empty Material and Effect object.
+ var material = g_pack.createObject('Material');
+ var effect = g_pack.createObject('Effect');
+
+ // Load shader string from document.
+ var shaderString = document.getElementById('effect').value;
+ effect.loadFromFXString(shaderString);
+
+ // Apply the effect to this material.
+ material.effect = effect;
+
+ // Bind uniform parameters declared in shader to parameters of material.
+ effect.createUniformParameters(material);
+
+ // Set the material's drawList.
+ material.drawList = g_viewInfo.performanceDrawList;
+
+ // Set light and camera positions for the pixel shader.
+ material.getParam('lightWorldPos').value = [3, 10, 0];
+ material.getParam('cameraWorldPos').value = [1, 3, 12];
+
+ // Look up clock param.
+ g_clockParam = material.getParam('clock');
+
+ return material;
+}
+
+
+/**
+ * Creates the plane using the primitives utility library, and adds it to the
+ * transform graph at the root node.
+ */
+function createPlane() {
+ // This will create a plane subdivided into 80,000 triangles.
+ var plane = o3djs.primitives.createPlane(
+ g_pack, createMaterial(), 4, 4, 200, 200);
+
+ // Add the shape to the transform hierarchy.
+ g_client.root.addShape(plane);
+}
+
+
+/**
+ * Updates the clock for the animation.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ // Update g_clock in the browser and cache a V8 copy that can be
+ // accessed efficiently. g_clock must be in the browser for selenium.
+ var clock = window.g_clock + elapsedTime * window.g_timeMult;
+ window.g_clock = clock;
+
+ g_clockParam.value = clock;
+}
+
+
+/**
+ * Cleanup before exiting.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body onload="init()" onunload="unload()">
+<h1>Vertex Shader</h1>
+This sample uses a custom vertex shader to quickly adjust the positions and
+normals of many vertices in a plane to achieve a ripple effect without iterating
+through the vertices in javascript.
+<br/>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 600px; height: 600px;"></div>
+<!-- End of O3D plugin -->
+
+<!-- Text area to hold the shaders -->
+<textarea id="effect" name="effect" cols="80" rows="20"
+ style="display: none;">
+uniform mat4 world;
+uniform mat4 worldViewProjection;
+uniform mat4 worldInverseTranspose;
+
+uniform float clock;
+
+// Input parameters for the vertex shader.
+attribute vec4 position;
+attribute vec3 normal;
+attribute vec4 color;
+
+// Input parameters for the pixel shader (also the output parameters for the
+// vertex shader.)
+varying vec3 v_objectPosition;
+varying vec3 v_normal;
+varying vec4 v_color;
+
+/**
+ * A function defining the shape of the wave. Takes a single vec2 as an
+ * argument the entries of which are the x and z components of a point in the
+ * plane. Returns the height of that point.
+ *
+ * @param {vec2} v The x and z components of the point in a single vec2.
+ */
+float wave(vec2 v) {
+ float d = length(v);
+ return 0.15 * sin(15.0 * d - 5.0 * clock) / (1.0 + d * d);
+}
+
+
+/**
+ * vertexShaderFunction - The vertex shader perturbs the vertices of the plane
+ * to achieve the ripples. Then it applies the worldViewProjection matrix.
+ *
+ * @param input.position Position vector of vertex in object coordinates.
+ * @param input.normal Normal of vertex in object coordinates.
+ * @param input.color Color of vertex.
+ */
+void main() {
+ vec4 p = position;
+
+ // The height of the point p is adjusted according to the wave function.
+ p.y = wave(p.xz);
+
+ // Step size used to approximate the partial derivatives of the wave function.
+ float h = 0.001;
+
+ // We take the derivative numerically so that the wave function can be
+ // modified and the normal will still be correct.
+ vec3 n = normalize(vec3(
+ wave(vec2(p.x - h, p.z)) - wave(vec2(p.x + h, p.z)), 2.0 * h,
+ wave(vec2(p.x, p.z - h)) - wave(vec2(p.x, p.z + h))));
+
+ gl_Position = worldViewProjection * p;
+ v_objectPosition = (world * p).xyz;
+ v_normal = (worldInverseTranspose * vec4(n, 1.0)).xyz;
+ v_color = color;
+}
+
+// #o3d SplitMarker
+
+uniform float clock;
+uniform vec3 lightWorldPos;
+uniform vec3 cameraWorldPos;
+
+varying vec3 v_objectPosition;
+varying vec3 v_normal;
+varying vec4 v_color;
+
+/**
+ * This pixel shader is meant to be minimal since the vertex shader is
+ * the focus of the sample.
+ */
+void main() {
+ vec3 p = v_objectPosition; // The point in question.
+ vec3 l = normalize(lightWorldPos - p); // Unit-length vector toward light.
+ vec3 n = normalize(v_normal); // Unit-length normal vector.
+ vec3 v = normalize(cameraWorldPos - p); // Unit-length vector toward camera.
+ vec3 r = normalize(-reflect(v, n)); // Reflection of v across n.
+
+ vec3 q = (lightWorldPos - p);
+ float ldotr = dot(r, l);
+ float specular = clamp(ldotr, 0.0, 1.0) /
+ (1.0 + length(q - length(q) * ldotr * r));
+
+ // Fixed color to be a blue-green; could use v_color instead below.
+ gl_FragColor = vec4(0, 0.6, 0.7, 1) * dot(n, l) + specular;
+}
+
+// #o3d MatrixLoadOrder RowMajor
+</textarea>
+</body>
+</html>
diff --git a/o3d/samples/shaders/phong-vertex-anim-glsl.shader b/o3d/samples/shaders/phong-vertex-anim-glsl.shader
new file mode 100644
index 0000000..1a45b47
--- /dev/null
+++ b/o3d/samples/shaders/phong-vertex-anim-glsl.shader
@@ -0,0 +1,100 @@
+/*
+ * 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 shader expects to be passed vertices that are part of an x-z plane mesh
+// because it assumes the normal for each vertex before being offset by the
+// animation is 0, 1, 0.
+
+uniform mat4 viewProjection;
+uniform mat4 world;
+uniform mat4 worldInverseTranspose;
+uniform float time;
+
+attribute vec4 position;
+
+varying vec3 v_normal;
+varying vec3 v_worldPosition;
+
+void main() {
+ vec3 worldPosition = (world * position).xyz;
+
+ float animValue = time + (worldPosition.x + worldPosition.z) * 0.4;
+ float animSin = sin(animValue);
+ float animCos = cos(animValue);
+ vec4 position = vec4(
+ worldPosition.x,
+ worldPosition.y + animSin,
+ worldPosition.z,
+ 1);
+ gl_Position = viewProjection * position;
+ vec3 normalTmp = normalize(vec3(animCos, abs(animSin), animCos));
+ v_normal = (worldInverseTranspose * vec4(normalTmp, 0)).xyz;
+ v_worldPosition = position.xyz;
+}
+
+// #o3d SplitMarker
+
+uniform vec3 lightWorldPos;
+uniform vec4 lightIntensity;
+uniform vec4 ambientIntensity;
+uniform vec4 emissive;
+uniform vec4 ambient;
+uniform vec4 diffuse;
+uniform vec4 specular;
+uniform float shininess;
+uniform float time;
+uniform mat4 viewInverse;
+
+varying vec3 v_normal;
+varying vec3 v_worldPosition;
+
+vec4 lit(float l ,float h, float m) {
+ return vec4(1.0,
+ max(l, 0.0),
+ (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+ 1.0);
+}
+
+void main() {
+ vec3 surfaceToLight = normalize(lightWorldPos - v_worldPosition);
+ vec3 worldNormal = normalize(v_normal);
+ vec3 surfaceToView = normalize(viewInverse[3].xyz - v_worldPosition);
+ vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+ vec4 litResult = lit(dot(worldNormal, surfaceToLight),
+ dot(worldNormal, halfVector), shininess);
+ vec4 outColor = ambientIntensity * ambient;
+ outColor += lightIntensity * (diffuse * litResult.y +
+ specular * litResult.z);
+ outColor += emissive;
+ gl_FragColor = vec4(outColor.rgb, diffuse.a);
+}
+
+// #o3d MatrixLoadOrder RowMajor