summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorpathorn@chromium.org <pathorn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-29 01:52:41 +0000
committerpathorn@chromium.org <pathorn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-29 01:52:41 +0000
commitf06d8fe26d2a552d50b5c479f2a867f74463e4a8 (patch)
treea38bf4fcdf78d0eb4a38d2c603c4c10315e6e29b /o3d
parent390981bf1601c8eb9c7a9e6b817ef854328de467 (diff)
downloadchromium_src-f06d8fe26d2a552d50b5c479f2a867f74463e4a8.zip
chromium_src-f06d8fe26d2a552d50b5c479f2a867f74463e4a8.tar.gz
chromium_src-f06d8fe26d2a552d50b5c479f2a867f74463e4a8.tar.bz2
Multiple simple lights, and a new demo.
Review URL: http://codereview.chromium.org/3358020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60900 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/samples/multiple-lights.html208
-rw-r--r--o3d/samples/o3d-webgl-samples/multiple-lights.html209
-rw-r--r--o3d/samples/o3djs/effect.js148
-rw-r--r--o3d/samples/o3djs/material.js28
-rw-r--r--o3d/samples/o3djs/pack.js5
5 files changed, 544 insertions, 54 deletions
diff --git a/o3d/samples/multiple-lights.html b/o3d/samples/multiple-lights.html
new file mode 100644
index 0000000..5817ac7
--- /dev/null
+++ b/o3d/samples/multiple-lights.html
@@ -0,0 +1,208 @@
+<!--
+Copyright 2010, 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 Multiple Lights example.
+
+Shows a simple cube with one light on each corner.
+-->
+<!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>
+Multiple Lights
+</title>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript" id="o3dscript">
+
+//o3djs.base.o3d = o3d;
+
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.primitives');
+
+// Events
+// init() 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_viewInfo;
+var g_pack;
+var g_transform = null;
+var g_finished = false; // for selenium testing.
+var g_clock = 0;
+var g_timeMult = 1;
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ var o3dElement = clientElements[0];
+ g_o3d = o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = o3dElement.client;
+
+ // Creates 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);
+
+ // Set our projection matrix, with a vertical field of view of 45 degrees
+ // a near clipping plane of 0.1 and far clipping plane of 10000.
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45),
+ g_client.width / g_client.height,
+ 0.1,
+ 10000);
+
+ // Create a material.
+ var material = g_pack.createObject('Material');
+ material.drawList = g_viewInfo.performanceDrawList;
+
+ material.createParam('diffuse', 'ParamFloat4').value = [.5, .5, .5, 1];
+
+ // Create some suitable defaults for the material to save the user having
+ // to know all this stuff right off the bat.
+ material.createParam('emissive', 'ParamFloat4').value = [0, 0, 0, 1];
+ material.createParam('ambient', 'ParamFloat4').value = [0, 0, 0, 0];
+ material.createParam('specular', 'ParamFloat4').value = [1, 1, 1, 1];
+ material.createParam('shininess', 'ParamFloat').value = 10;
+ material.createParam('specularFactor', 'ParamFloat').value = 1;
+ o3djs.material.attachStandardEffect(
+ g_pack,
+ material,
+ g_viewInfo,
+ 'blinn',
+ {lights: 8});
+ var materialColorParamList = material.getParam('lightColorList');
+ var colorParamList = g_pack.createObject('ParamArray');
+ var materialLightPositionList = material.getParam('lightWorldPosList');
+ var lightPositionParamList = g_pack.createObject('ParamArray');
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCube(
+ g_pack,
+ material,
+ 150);
+
+ g_transform = g_pack.createObject('Transform');
+ // Add the cylinder to the root transform.
+ g_transform.addShape(shape);
+ g_transform.parent = g_client.root;
+
+ var colors = [
+ [0, 0, 0, 1], // null light
+ [1, 0, 0, 1],
+ [0, 0, 1, 1],
+ [0, 1, 0, 1],
+ [1, 1, 1, 1],
+ [0, 1, 1, 1],
+ [1, 1, 0, 1],
+ [1, 0, 1, 1]];
+ var lightDist = 150;
+ for (var i = 0; i < 8; i++) {
+ colorParamList.createParam(i,'ParamFloat4').value = colors[i];
+ var position = [
+ (i&1)?lightDist:-lightDist,
+ (i&2)?lightDist:-lightDist,
+ (i&4)?lightDist:-lightDist
+ ];
+ lightPositionParamList.createParam(i,'ParamFloat3').value = position;
+ }
+ materialLightPositionList.value = lightPositionParamList;
+ materialColorParamList.value = colorParamList;
+ // Setup an onrender callback for animation.
+ g_client.setRenderCallback(onrender);
+
+ g_finished = true; // for selenium testing.
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Info for rendering.
+ */
+function onrender(renderEvent) {
+ // Get the number of seconds since the last render.
+ var elapsedTime = renderEvent.elapsedTime;
+ g_clock += elapsedTime * g_timeMult;
+
+ var x = Math.sin(g_clock * 0.3) * 400;
+ var z = Math.cos(g_clock * 0.3) * 400;
+ var y = Math.sin(g_clock * 0.7) * 200 + 100;
+
+ // spin the camera.
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [x, y, z], // eye
+ [0, 0, 0], // target
+ [0, 1, 0]); // up
+}
+
+/**
+ * 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>
+<h1>Multiple Lights</h1>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 600px; height: 400px;"></div>
+<!-- End of O3D plugin -->
+</body>
+</html>
diff --git a/o3d/samples/o3d-webgl-samples/multiple-lights.html b/o3d/samples/o3d-webgl-samples/multiple-lights.html
new file mode 100644
index 0000000..e0f4ef5
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/multiple-lights.html
@@ -0,0 +1,209 @@
+<!--
+Copyright 2010, 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 Multiple Lights example.
+
+Shows a simple cube with one light on each corner.
+-->
+<!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>
+Multiple Lights
+</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>
+
+<!-- Our javascript code -->
+<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.material');
+o3djs.require('o3djs.primitives');
+
+// Events
+// init() 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_viewInfo;
+var g_pack;
+var g_transform = null;
+var g_finished = false; // for selenium testing.
+var g_clock = 0;
+var g_timeMult = 1;
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ var o3dElement = clientElements[0];
+ g_o3d = o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = o3dElement.client;
+
+ // Creates 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);
+
+ // Set our projection matrix, with a vertical field of view of 45 degrees
+ // a near clipping plane of 0.1 and far clipping plane of 10000.
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45),
+ g_client.width / g_client.height,
+ 0.1,
+ 10000);
+
+ // Create a material.
+ var material = g_pack.createObject('Material');
+ material.drawList = g_viewInfo.performanceDrawList;
+
+ material.createParam('diffuse', 'ParamFloat4').value = [.5, .5, .5, 1];
+
+ // Create some suitable defaults for the material to save the user having
+ // to know all this stuff right off the bat.
+ material.createParam('emissive', 'ParamFloat4').value = [0, 0, 0, 1];
+ material.createParam('ambient', 'ParamFloat4').value = [0, 0, 0, 0];
+ material.createParam('specular', 'ParamFloat4').value = [1, 1, 1, 1];
+ material.createParam('shininess', 'ParamFloat').value = 10;
+ material.createParam('specularFactor', 'ParamFloat').value = 1;
+ o3djs.material.attachStandardEffect(
+ g_pack,
+ material,
+ g_viewInfo,
+ 'blinn',
+ {lights: 8});
+ var materialColorParamList = material.getParam('lightColorList');
+ var colorParamList = g_pack.createObject('ParamArray');
+ var materialLightPositionList = material.getParam('lightWorldPosList');
+ var lightPositionParamList = g_pack.createObject('ParamArray');
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCube(
+ g_pack,
+ material,
+ 150);
+
+ g_transform = g_pack.createObject('Transform');
+ // Add the cylinder to the root transform.
+ g_transform.addShape(shape);
+ g_transform.parent = g_client.root;
+
+ var colors = [
+ [0, 0, 0, 1], // null light
+ [1, 0, 0, 1],
+ [0, 0, 1, 1],
+ [0, 1, 0, 1],
+ [1, 1, 1, 1],
+ [0, 1, 1, 1],
+ [1, 1, 0, 1],
+ [1, 0, 1, 1]];
+ var lightDist = 150;
+ for (var i = 0; i < 8; i++) {
+ colorParamList.createParam(i,'ParamFloat4').value = colors[i];
+ var position = [
+ (i&1)?lightDist:-lightDist,
+ (i&2)?lightDist:-lightDist,
+ (i&4)?lightDist:-lightDist
+ ];
+ lightPositionParamList.createParam(i,'ParamFloat3').value = position;
+ }
+ materialLightPositionList.value = lightPositionParamList;
+ materialColorParamList.value = colorParamList;
+ // Setup an onrender callback for animation.
+ g_client.setRenderCallback(onrender);
+
+ g_finished = true; // for selenium testing.
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Info for rendering.
+ */
+function onrender(renderEvent) {
+ // Get the number of seconds since the last render.
+ var elapsedTime = renderEvent.elapsedTime;
+ g_clock += elapsedTime * g_timeMult;
+
+ var x = Math.sin(g_clock * 0.3) * 400;
+ var z = Math.cos(g_clock * 0.3) * 400;
+ var y = Math.sin(g_clock * 0.7) * 200 + 100;
+
+ // spin the camera.
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [x, y, z], // eye
+ [0, 0, 0], // target
+ [0, 1, 0]); // up
+}
+
+/**
+ * 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>
+<h1>Multiple Lights</h1>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 600px; height: 400px;"></div>
+<!-- End of O3D plugin -->
+</body>
+</html>
diff --git a/o3d/samples/o3djs/effect.js b/o3d/samples/o3djs/effect.js
index 221d781..558e1e2 100644
--- a/o3d/samples/o3djs/effect.js
+++ b/o3d/samples/o3djs/effect.js
@@ -466,7 +466,7 @@ o3djs.effect.buildVaryingDecls =
p.semanticSuffix('TEXCOORD' +
p.interpolant_++ + '') + ';\n' +
p.VARYING + p.FLOAT3 + ' ' +
- p.VARYING_DECLARATION_PREFIX + 'surfaceToLight' +
+ p.VARYING_DECLARATION_PREFIX + 'surfacePosition' +
p.semanticSuffix(
'TEXCOORD' + p.interpolant_++ + '') + ';\n';
}
@@ -836,12 +836,24 @@ o3djs.effect.createEffectFromFile = function(pack, url) {
*
* @param {!o3d.Material} material Material for which to build the shader.
* @param {string} effectType Type of effect to create ('phong', 'lambert',
- * 'constant').
+ * 'constant', 'blinn').
+ * @param {Object} opt_options Parameters to customize shader code generation.
+ See o3djs.effect.getStandardShader for details on the possible values.
* @return {{description: string, shader: string}} A description and the shader
* string.
*/
o3djs.effect.buildStandardShaderString = function(material,
- effectType) {
+ effectType,
+ opt_options) {
+ if (!opt_options) {
+ opt_options = {};
+ }
+ var numLights = 0;
+ var currentLightWorldPos = 'lightWorldPos';
+ if (opt_options.lights) {
+ numLights = opt_options.lights;
+ currentLightWorldPos = 'lightWorldPosList[i]';
+ }
var p = o3djs.effect;
var bumpSampler = material.getParam('bumpSampler');
var bumpUVInterpolant;
@@ -901,9 +913,9 @@ o3djs.effect.buildStandardShaderString = function(material,
* @return {string} The effect code for the common shader uniforms.
*/
var buildCommonVertexUniforms = function() {
+ //var size = numLights ? '['+numLights+']' : '';
return 'uniform ' + p.MATRIX4 + ' worldViewProjection' +
- p.semanticSuffix('WORLDVIEWPROJECTION') + ';\n' +
- 'uniform ' + p.FLOAT3 + ' lightWorldPos;\n';
+ p.semanticSuffix('WORLDVIEWPROJECTION') + ';\n';
};
/**
@@ -911,7 +923,13 @@ o3djs.effect.buildStandardShaderString = function(material,
* @return {string} The effect code for the common shader uniforms.
*/
var buildCommonPixelUniforms = function() {
- return 'uniform ' + p.FLOAT4 + ' lightColor;\n';
+ if (numLights > 0) {
+ return 'uniform ' + p.FLOAT4 + ' lightColorList[' + numLights + '];\n' +
+ 'uniform ' + p.FLOAT3 + ' lightWorldPosList[' + numLights + '];\n';
+ } else {
+ return 'uniform ' + p.FLOAT4 + ' lightColor;\n' +
+ 'uniform ' + p.FLOAT3 + ' lightWorldPos' + ';\n';
+ }
};
/**
@@ -991,6 +1009,37 @@ o3djs.effect.buildStandardShaderString = function(material,
};
/**
+ * Begins a section of code which is to be run once for each light.
+ * @return {string} The effect code for the for loop, or the empty string if
+ * not using multiple lights.
+ */
+ var beginLightLoop = function() {
+ if (numLights) {
+ return ' ' + p.FLOAT4 + ' lightColorDiffuse = ' + p.FLOAT4 + '(0);\n' +
+ ' for (int i = 0; i < ' + numLights + '; i++) {\n';
+ } else {
+ return '';
+ }
+ };
+
+ /**
+ * Ends the block of code which is to be run for each light. Adds the current
+ * light's color times (diffuseExpression) into lightColorDiffuse.
+ * @param {string} diffuseExpression Expression to multiply by light color.
+ * @return {string} The effect code to set lightColorDiffuse.
+ */
+ var endLightLoop = function(diffuseExpression) {
+ if (numLights) {
+ return ' lightColorDiffuse += ' +
+ 'lightColorList[i] * ( ' + diffuseExpression + ');\n' +
+ ' }\n';
+ } else {
+ return ' ' + p.FLOAT4 + ' lightColorDiffuse = ' +
+ 'lightColor * (' + diffuseExpression + ');';
+ }
+ };
+
+ /**
* Builds vertex and fragment shader string for the Constant lighting type.
* @param {!o3d.Material} material The material for which to build
* shaders.
@@ -1034,7 +1083,7 @@ o3djs.effect.buildStandardShaderString = function(material,
p.buildUVPassthroughs(material) +
positionVertexShaderCode() +
normalVertexShaderCode() +
- surfaceToLightVertexShaderCode() +
+ surfacePositionVertexShaderCode() +
bumpVertexShaderCode() +
p.endVertexShaderMain() +
p.pixelShaderHeader(material, true, false) +
@@ -1050,14 +1099,16 @@ o3djs.effect.buildStandardShaderString = function(material,
getColorParam(material, 'ambient') +
getColorParam(material, 'diffuse') +
getNormalShaderCode() +
- ' ' + p.FLOAT3 + ' surfaceToLight = normalize(' +
- p.PIXEL_VARYING_PREFIX + 'surfaceToLight);\n' +
- ' ' + p.FLOAT4 +
- ' litR = lit(dot(normal, surfaceToLight), 0.0, 0.0);\n' +
+ beginLightLoop() +
+ ' ' + p.FLOAT3 + ' surfaceToLight = normalize(' +
+ currentLightWorldPos + ' - ' +
+ p.PIXEL_VARYING_PREFIX + 'surfacePosition);\n' +
+ ' ' + p.FLOAT4 +
+ ' litR = lit(dot(normal, surfaceToLight), 0.0, 0.0);\n' +
+ endLightLoop('ambient * diffuse + diffuse * litR.y') +
p.endPixelShaderMain(p.FLOAT4 +
'((emissive +\n' +
- ' lightColor *' +
- ' (ambient * diffuse + diffuse * litR.y)).rgb,\n' +
+ ' lightColorDiffuse).rgb,\n' +
' diffuse.a)') +
p.entryPoints() +
p.matrixLoadOrder();
@@ -1082,7 +1133,7 @@ o3djs.effect.buildStandardShaderString = function(material,
p.buildUVPassthroughs(material) +
positionVertexShaderCode() +
normalVertexShaderCode() +
- surfaceToLightVertexShaderCode() +
+ surfacePositionVertexShaderCode() +
surfaceToViewVertexShaderCode() +
bumpVertexShaderCode() +
p.endVertexShaderMain() +
@@ -1103,22 +1154,21 @@ o3djs.effect.buildStandardShaderString = function(material,
getColorParam(material, 'diffuse') +
getColorParam(material, 'specular') +
getNormalShaderCode() +
- ' ' + p.FLOAT3 + ' surfaceToLight = normalize(' +
- p.PIXEL_VARYING_PREFIX + 'surfaceToLight);\n' +
' ' + p.FLOAT3 + ' surfaceToView = normalize(' +
p.PIXEL_VARYING_PREFIX + 'surfaceToView);\n' +
- ' ' + p.FLOAT3 +
- ' halfVector = normalize(surfaceToLight + ' +
- p.PIXEL_VARYING_PREFIX + 'surfaceToView);\n' +
- ' ' + p.FLOAT4 +
+ beginLightLoop() +
+ ' ' + p.FLOAT3 + ' surfaceToLight = normalize(' +
+ currentLightWorldPos + ' - ' +
+ p.PIXEL_VARYING_PREFIX + 'surfacePosition);\n' +
+ ' ' + p.FLOAT3 +
+ ' halfVector = normalize(surfaceToLight + surfaceToView);\n' +
+ ' ' + p.FLOAT4 +
' litR = lit(dot(normal, surfaceToLight), \n' +
' dot(normal, halfVector), shininess);\n' +
+ endLightLoop('ambient * diffuse + diffuse * litR.y\n' +
+ ' + specular * litR.z * specularFactor') +
p.endPixelShaderMain( p.FLOAT4 +
- '((emissive +\n' +
- ' lightColor *' +
- ' (ambient * diffuse + diffuse * litR.y +\n' +
- ' + specular * litR.z *' +
- ' specularFactor)).rgb,\n' +
+ '((emissive + lightColorDiffuse).rgb,\n' +
' diffuse.a)') +
p.entryPoints() +
p.matrixLoadOrder();
@@ -1141,7 +1191,7 @@ o3djs.effect.buildStandardShaderString = function(material,
p.buildUVPassthroughs(material) +
positionVertexShaderCode() +
normalVertexShaderCode() +
- surfaceToLightVertexShaderCode() +
+ surfacePositionVertexShaderCode() +
surfaceToViewVertexShaderCode() +
bumpVertexShaderCode() +
p.endVertexShaderMain() +
@@ -1162,20 +1212,21 @@ o3djs.effect.buildStandardShaderString = function(material,
getColorParam(material, 'diffuse') +
getColorParam(material, 'specular') +
getNormalShaderCode() +
- ' ' + p.FLOAT3 + ' surfaceToLight = normalize(' +
- p.PIXEL_VARYING_PREFIX + 'surfaceToLight);\n' +
' ' + p.FLOAT3 + ' surfaceToView = normalize(' +
p.PIXEL_VARYING_PREFIX + 'surfaceToView);\n' +
- ' ' + p.FLOAT3 +
+ beginLightLoop() +
+ ' ' + p.FLOAT3 + ' surfaceToLight = normalize(' +
+ currentLightWorldPos + ' - ' +
+ p.PIXEL_VARYING_PREFIX + 'surfacePosition);\n' +
+ ' ' + p.FLOAT3 +
' halfVector = normalize(surfaceToLight + surfaceToView);\n' +
- ' ' + p.FLOAT4 +
+ ' ' + p.FLOAT4 +
' litR = lit(dot(normal, surfaceToLight), \n' +
' dot(normal, halfVector), shininess);\n' +
+ endLightLoop('ambient * diffuse + diffuse * litR.y +\n' +
+ ' + specular * litR.z * specularFactor') +
p.endPixelShaderMain(p.FLOAT4 +
- '((emissive +\n' +
- ' lightColor * (ambient * diffuse + diffuse * litR.y +\n' +
- ' + specular * litR.z *' +
- ' specularFactor)).rgb,\n' +
+ '((emissive + lightColorDiffuse).rgb,\n' +
' diffuse.a)') +
p.entryPoints() +
p.matrixLoadOrder();
@@ -1240,13 +1291,14 @@ o3djs.effect.buildStandardShaderString = function(material,
};
/**
- * Builds the surface to light code for the vertex shader.
+ * Builds the surface position code for the vertex shader. To support
+ * multiple lights, the dot product with each light should then be
+ * computed in the fragment shader.
* @return {string} The code for the vertex shader.
*/
- var surfaceToLightVertexShaderCode = function() {
+ var surfacePositionVertexShaderCode = function() {
return ' ' + p.VERTEX_VARYING_PREFIX +
- 'surfaceToLight = lightWorldPos - \n' +
- ' ' +
+ 'surfacePosition = \n' +
p.mul(p.ATTRIBUTE_PREFIX + 'position',
'world') + '.xyz;\n';
};
@@ -1346,14 +1398,19 @@ o3djs.effect.buildStandardShaderString = function(material,
* @param {!o3d.Pack} pack Pack in which to create the new Effect.
* @param {!o3d.Material} material Material for which to build the shader.
* @param {string} effectType Type of effect to create ('phong', 'lambert',
- * 'constant').
+ * 'constant', 'blinn').
+ * @param {{lights: number}} opt_options Extra options.
+ * If 'lights' is non-zero, creates an array of light params; otherwise
+ * only a single light is supported.
* @return {o3d.Effect} The created effect.
*/
o3djs.effect.getStandardShader = function(pack,
material,
- effectType) {
+ effectType,
+ opt_options) {
var record = o3djs.effect.buildStandardShaderString(material,
- effectType);
+ effectType,
+ opt_options);
var effects = pack.getObjectsByClassName('o3d.Effect');
for (var ii = 0; ii < effects.length; ++ii) {
if (effects[ii].name == record.description &&
@@ -1383,16 +1440,19 @@ o3djs.effect.getStandardShader = function(pack,
* @param {!o3d.Material} material Material for which to build the shader.
* @param {!o3djs.math.Vector3} lightPos Position of the default light.
* @param {string} effectType Type of effect to create ('phong', 'lambert',
- * 'constant').
+ * 'constant', 'blinn').
+ * @param {Object} opt_options Extra options for effect.getStandardShader
* @return {boolean} True on success.
*/
o3djs.effect.attachStandardShader = function(pack,
material,
lightPos,
- effectType) {
+ effectType,
+ opt_options) {
var effect = o3djs.effect.getStandardShader(pack,
material,
- effectType);
+ effectType,
+ opt_options);
if (effect) {
material.effect = effect;
effect.createUniformParameters(material);
diff --git a/o3d/samples/o3djs/material.js b/o3d/samples/o3djs/material.js
index 7ba3c8e..4a166b8 100644
--- a/o3d/samples/o3djs/material.js
+++ b/o3d/samples/o3djs/material.js
@@ -113,13 +113,15 @@ o3djs.material.hasNonOneAlpha_ = function(material, name) {
* @param {!o3d.Material} material to prepare.
* @param {string} opt_effectType type of effect to create ('phong',
* 'lambert', 'constant').
+ * @param {Object} opt_options Extra options for effect.getStandardShader
*
* @see o3djs.material.attachStandardEffect
*/
o3djs.material.prepareMaterial = function(pack,
viewInfo,
material,
- opt_effectType) {
+ opt_effectType,
+ opt_options) {
// Assume we want the performance list
var drawList = viewInfo.performanceDrawList;
// First check if we have a tag telling us that it is or is not
@@ -146,7 +148,8 @@ o3djs.material.prepareMaterial = function(pack,
o3djs.material.attachStandardEffect(pack,
material,
viewInfo,
- opt_effectType);
+ opt_effectType,
+ opt_options);
// For collada common profile stuff guess what drawList to use. Note: We
// can only do this for collada common profile stuff because we supply
// the shaders and therefore now the inputs and how they are used.
@@ -185,17 +188,20 @@ o3djs.material.prepareMaterial = function(pack,
* o3djs.rendergraph.createView.
* @param {!o3d.Pack} opt_effectPack Pack to create effects in. If this
* is not specifed the pack to prepare above will be used.
+ * @param {Object} opt_options Extra options for effect.getStandardShader
*
* @see o3djs.material.prepareMaterial
*/
o3djs.material.prepareMaterials = function(pack,
viewInfo,
- opt_effectPack) {
+ opt_effectPack,
+ opt_options) {
var materials = pack.getObjectsByClassName('o3d.Material');
for (var mm = 0; mm < materials.length; mm++) {
o3djs.material.prepareMaterial(opt_effectPack || pack,
viewInfo,
- materials[mm]);
+ materials[mm],
+ opt_options);
}
};
@@ -207,17 +213,20 @@ o3djs.material.prepareMaterials = function(pack,
* effect.
* @param {string} effectType Type of effect to create ('phong', 'lambert',
* 'constant').
+ * @param {Object} opt_options Extra options for effect.getStandardShader
*
* @see o3djs.effect.attachStandardShader
*/
o3djs.material.attachStandardEffectEx = function(pack,
material,
- effectType) {
+ effectType,
+ opt_options) {
if (!material.effect) {
if (!o3djs.effect.attachStandardShader(pack,
material,
[0, 0, 0],
- effectType)) {
+ effectType,
+ opt_options)) {
throw 'Could not attach a standard effect';
}
}
@@ -234,13 +243,15 @@ o3djs.material.attachStandardEffectEx = function(pack,
* o3djs.rendergraph.createView.
* @param {string} effectType Type of effect to create ('phong', 'lambert',
* 'constant').
+ * @param {Object} opt_options Extra options for effect.getStandardShader
*
* @see o3djs.effect.attachStandardShader
*/
o3djs.material.attachStandardEffect = function(pack,
material,
viewInfo,
- effectType) {
+ effectType,
+ opt_options) {
if (!material.effect) {
var lightPos =
o3djs.math.matrix4.getTranslation(
@@ -248,7 +259,8 @@ o3djs.material.attachStandardEffect = function(pack,
if (!o3djs.effect.attachStandardShader(pack,
material,
lightPos, // TODO(gman): remove this
- effectType)) {
+ effectType,
+ opt_options)) {
throw 'Could not attach a standard effect';
}
}
diff --git a/o3d/samples/o3djs/pack.js b/o3d/samples/o3djs/pack.js
index 3e4d086..183b315 100644
--- a/o3d/samples/o3djs/pack.js
+++ b/o3d/samples/o3djs/pack.js
@@ -59,12 +59,13 @@ o3djs.pack = o3djs.pack || {};
* o3djs.rendergraph.createView.
* @param {!o3d.Pack} opt_effectPack Pack to create effects in. If this is
* not specifed the pack to prepare above will be used.
+ * @param {Object} opt_options Extra options for effect.getStandardShader
*
* @see o3djs.material.prepareMaterials
* @see o3djs.shape.prepareShapes
*/
-o3djs.pack.preparePack = function(pack, viewInfo, opt_effectPack) {
- o3djs.material.prepareMaterials(pack, viewInfo, opt_effectPack);
+o3djs.pack.preparePack = function(pack, viewInfo, opt_effectPack, opt_options) {
+ o3djs.material.prepareMaterials(pack, viewInfo, opt_effectPack, opt_options);
o3djs.shape.prepareShapes(pack);
};