diff options
author | pathorn@chromium.org <pathorn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-29 01:52:41 +0000 |
---|---|---|
committer | pathorn@chromium.org <pathorn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-29 01:52:41 +0000 |
commit | f06d8fe26d2a552d50b5c479f2a867f74463e4a8 (patch) | |
tree | a38bf4fcdf78d0eb4a38d2c603c4c10315e6e29b /o3d | |
parent | 390981bf1601c8eb9c7a9e6b817ef854328de467 (diff) | |
download | chromium_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.html | 208 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/multiple-lights.html | 209 | ||||
-rw-r--r-- | o3d/samples/o3djs/effect.js | 148 | ||||
-rw-r--r-- | o3d/samples/o3djs/material.js | 28 | ||||
-rw-r--r-- | o3d/samples/o3djs/pack.js | 5 |
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); }; |