summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 01:12:11 +0000
committerluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 01:12:11 +0000
commitd89ea3ced6389f04190eaa5431d32f67bca0056d (patch)
treec66dcde04e8e73c5d00d7f6fba92d485101e2ecd /o3d
parent7f7506f4f67c880b033d723dd1b7c29eac30dfac (diff)
downloadchromium_src-d89ea3ced6389f04190eaa5431d32f67bca0056d.zip
chromium_src-d89ea3ced6389f04190eaa5431d32f67bca0056d.tar.gz
chromium_src-d89ea3ced6389f04190eaa5431d32f67bca0056d.tar.bz2
Implemented error texture support in client and ParamArray class. Fixed bug in effect.js that broke checkerboard texture if running using CG shaders.
TODO: Still a bug with render surface sets; will file issue and tackle problem in separate CL. Review URL: http://codereview.chromium.org/2803007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52248 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/samples/o3d-webgl-samples/convolution.html398
-rw-r--r--o3d/samples/o3d-webgl-samples/error-texture.html265
-rw-r--r--o3d/samples/o3d-webgl/base.js1
-rw-r--r--o3d/samples/o3d-webgl/client.js91
-rw-r--r--o3d/samples/o3d-webgl/effect.js114
-rw-r--r--o3d/samples/o3d-webgl/param.js41
-rw-r--r--o3d/samples/o3d-webgl/param_array.js184
-rw-r--r--o3d/samples/o3d-webgl/param_object.js1
-rw-r--r--o3d/samples/o3d-webgl/sampler.js37
-rw-r--r--o3d/samples/o3djs/effect.js8
10 files changed, 1091 insertions, 49 deletions
diff --git a/o3d/samples/o3d-webgl-samples/convolution.html b/o3d/samples/o3d-webgl-samples/convolution.html
new file mode 100644
index 0000000..bc09031
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/convolution.html
@@ -0,0 +1,398 @@
+<!--
+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 separable convolution shader using
+render targets. The kernel here is a Gaussian blur, but the same code
+could be used for any kernel.
+-->
+<!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: Convolution 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.camera');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.pack');
+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.
+ * @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 whose 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 texture1 = g_pack.createTexture2D(RENDER_TARGET_WIDTH,
+ RENDER_TARGET_HEIGHT,
+ g_o3d.Texture.XRGB8, 1, true);
+
+ // Create the texture required for the color render-target.
+ var texture2 = 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 xSigma = 4.0, ySigma = 4.0;
+ var xKernel = buildKernel(xSigma);
+ var yKernel = buildKernel(ySigma);
+
+ var renderSurfaceSet1 = createRenderSurfaceSet(texture1);
+ var renderSurfaceSet2 = createRenderSurfaceSet(texture2);
+
+ // Create the render graph for the teapot view, drawing the teapot into
+ // texture1 (via renderSurfaceSet1).
+ var teapotViewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_teapotRoot,
+ renderSurfaceSet1,
+ [1, 1, 1, 1]);
+
+ // Create a Y convolution pass that convolves texture1 into texture2, using
+ // the X kernel.
+ var renderNode1 = createConvolutionPass(texture1,
+ renderSurfaceSet2,
+ xKernel,
+ 1.0 / texture1.width,
+ 0.0);
+
+ // Create a Y convolution pass that convolves texture2 into the framebuffer,
+ // using the Y kernel.
+ var renderNode2 = createConvolutionPass(texture2,
+ g_client.renderGraphRoot,
+ yKernel,
+ 0.0,
+ 1.0 / texture2.height);
+
+ // 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);
+}
+
+// We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize
+// anyway.
+function gauss(x, sigma) {
+ return Math.exp(- (x * x) / (2.0 * sigma * sigma));
+}
+
+function buildKernel(sigma) {
+ var kMaxKernelSize = 25;
+ var kernelSize = 2 * Math.ceil(sigma * 3.0) + 1;
+ if (kernelSize > kMaxKernelSize) {
+ kernelSize = kMaxKernelSize;
+ }
+ var halfWidth = (kernelSize - 1) * 0.5
+ var values = new Array(kernelSize);
+ var sum = 0.0;
+ for (var i = 0; i < kernelSize; ++i) {
+ values[i] = gauss(i - halfWidth, sigma);
+ sum += values[i];
+ }
+ // Now normalize the kernel.
+ for (var i = 0; i < kernelSize; ++i) {
+ values[i] /= sum;
+ }
+ return values;
+}
+
+function createConvolutionMaterial(viewInfo, kernelSize) {
+ var convFXString = document.getElementById('convFX').value;
+ convFXString = convFXString.replace(/KERNEL_WIDTH/g, kernelSize);
+ 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 createConvolutionPass(srcTexture, renderGraphRoot, kernel, x, y) {
+ // Create a root Transform for the convolution scene.
+ var root = g_pack.createObject('Transform');
+
+ // Create a basic view for the convolution scene.
+ var viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ root,
+ renderGraphRoot,
+ [1, 1, 1, 1]);
+
+ var material = createConvolutionMaterial(viewInfo, kernel.length);
+ var quadShape = o3djs.primitives.createPlane(g_pack,
+ material,
+ 2.0,
+ 2.0,
+ 1,
+ 1);
+
+ // Attach the quad to the root of the convolution graph.
+ 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
+ // convolution scene.
+ o3djs.pack.preparePack(g_pack, viewInfo);
+
+ setConvolutionParameters(material, srcTexture, kernel, kernel.length, x, y);
+ return renderGraphRoot;
+}
+
+function setConvolutionParameters(material, texture, kernel, kernelSize,
+ xIncrement, yIncrement) {
+ var imageParam = material.getParam('image');
+ var kernelParam = material.getParam('kernel');
+ 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 = [xIncrement, yIncrement];
+ var paramArray = g_pack.createObject('ParamArray');
+ var halfWidth = (kernelSize - 1) * 0.5;
+ for (var i = 0; i < kernelSize; ++i) {
+ var element = paramArray.createParam(i, 'ParamFloat');
+ element.value = kernel[i];
+ }
+ kernelParam.value = paramArray;
+}
+
+/**
+ * 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>Convolution Shader Example</h1>
+<p>This sample shows how to do 2D image processing using render targets. This
+sample uses a convolution shader to do a 2D Gaussian blur, but the
+same code could be used for any separable convolution kernel.</p>
+<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;
+uniform vec2 imageIncrement;
+
+attribute vec4 position;
+attribute vec2 texCoord0;
+
+varying vec2 v_imageCoord;
+
+void main() {
+ gl_Position = worldViewProjection * position;
+
+ // Offset image coords by half of kernel width, in image texels
+ v_imageCoord = texCoord0 -
+ (float(KERNEL_WIDTH - 1) / 2.0) * imageIncrement;
+}
+
+// #o3d SplitMarker
+
+uniform sampler2D image;
+uniform float kernel[ KERNEL_WIDTH ];
+uniform vec2 imageIncrement;
+
+varying vec2 v_imageCoord;
+
+void main() {
+ vec2 imageCoordTmp = v_imageCoord;
+ vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
+ for (int i = 0; i < KERNEL_WIDTH; ++i) {
+ sum += texture2D(image, imageCoordTmp) * kernel[i];
+ imageCoordTmp += imageIncrement;
+ }
+ gl_FragColor = sum;
+}
+
+// #o3d MatrixLoadOrder RowMajor
+</textarea>
+</div>
+</body>
+
+</html>
diff --git a/o3d/samples/o3d-webgl-samples/error-texture.html b/o3d/samples/o3d-webgl-samples/error-texture.html
new file mode 100644
index 0000000..b415f44
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/error-texture.html
@@ -0,0 +1,265 @@
+<!--
+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 attempts to show what the error texture is, how to set it and
+how turning it off will generate helpful error information.
+-->
+<html>
+<head>
+<title>Error Texture</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');
+o3djs.require('o3djs.effect');
+
+// Events
+// Run the init() once the page has finished loading.
+// and 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_pack;
+var g_viewInfo;
+var g_texture;
+var g_errorMsgElement;
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D, loads the effect, and sets up some 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;
+
+ g_errorMsgElement =
+ document.getElementById('errorMsg');
+
+ // Turn of the error callback that o3djs.base.init setup.
+ g_client.clearErrorCallback();
+
+ // Let us render on demand.
+ g_client.renderMode = g_o3d.Client.RENDERMODE_ON_DEMAND;
+
+ // 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);
+
+ var clientWidth = g_client.width;
+ var clientHeight = g_client.height;
+ g_viewInfo.drawContext.projection = g_math.matrix4.orthographic(
+ -clientWidth * 0.5,
+ clientWidth * 0.5,
+ -clientHeight * 0.5,
+ clientHeight * 0.5,
+ 0.001,
+ 1000);
+
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [0, 500, 0], // eye
+ [0, 0, 0], // target
+ [0, 0, -1]); // up
+
+ // Create and load the effect.
+ var effect = g_pack.createObject('Effect');
+ o3djs.effect.loadEffect(effect, '../shaders/texture-only-glsl.shader');
+
+ // Create a Material for the effect.
+ var myMaterial = g_pack.createObject('Material');
+
+ // Set the material's drawList
+ myMaterial.drawList = g_viewInfo.zOrderedDrawList;
+
+ // Apply our effect to this material.
+ myMaterial.effect = effect;
+
+ // Creates a quad using the effect.
+ var shape = o3djs.primitives.createPlane(g_pack,
+ myMaterial,
+ 1,
+ 1,
+ 1,
+ 1);
+
+ var pixels = [];
+ for (var y = 0; y < 32; ++y) {
+ for (var x = 0; x < 32; ++x) {
+ var offset = (y * 32 + x) * 3; // rgb
+ var u = x / 32 * Math.PI * 0.5;
+ var v = y / 32 * Math.PI * 0.5;
+ pixels[offset + 0] = 0; // red
+ pixels[offset + 1] = Math.floor(y / 8) % 2; // green
+ pixels[offset + 2] = Math.floor(x / 8) % 2; // blue
+ }
+ }
+ var texture = g_pack.createTexture2D(32, 32, g_o3d.Texture.XRGB8, 1, false);
+ texture.set(0, pixels);
+
+ // display the quad 4 times with situations
+ // by overriding the sampler on each instance.
+ for (var s = 0; s < 4; ++s) {
+ // create a transform for an instance
+ var transform = g_pack.createObject('Transform');
+ transform.translate((s - 1.5) * 140, 0, 0);
+ transform.scale(128, 1, 128),
+ transform.parent = g_client.root;
+ transform.addShape(shape);
+
+ // case 0: Correct Texture.
+ // case 1: ParamSampler and Sampler but no Texture
+ // case 2: ParamSampler but no Sampler,
+ // case 3: No ParamSampler.
+ if (s <= 2) {
+ // Create a ParamSampler on the transform with the same name as in
+ // the effect so this param will be used instead of the one on the
+ // material.
+ var samplerParam = transform.createParam('texSampler0', 'ParamSampler');
+
+ if (s <= 1) {
+ var sampler = g_pack.createObject('Sampler');
+ sampler.name = "s2d";
+ samplerParam.value = sampler;
+ sampler.addressModeU = g_o3d.Sampler.CLAMP;
+ sampler.addressModeV = g_o3d.Sampler.CLAMP;
+ if (s == 0) {
+ sampler.texture = texture;
+ }
+ }
+ }
+ }
+
+ g_client.setPostRenderCallback(onRender);
+
+ // Render once now that things are setup.
+ render();
+}
+
+function setToUserTexture() {
+ var pixels = [];
+ for (var y = 0; y < 32; ++y) {
+ for (var x = 0; x < 32; ++x) {
+ var offset = (y * 32 + x) * 3; // rgb
+ var u = x / 32 * Math.PI * 0.5;
+ var v = y / 32 * Math.PI * 0.5;
+ pixels[offset + 0] = Math.cos(u); // red
+ pixels[offset + 1] = Math.sin(v); // green
+ pixels[offset + 2] = Math.sin(u); // blue
+ }
+ }
+ var texture = g_pack.createTexture2D(32, 32, g_o3d.Texture.XRGB8, 1, false);
+ texture.set(0, pixels);
+
+ g_client.setErrorTexture(texture);
+ // Render once now that things are setup.
+ render();
+}
+
+function setToNoTexture() {
+ g_client.setErrorTexture(null);
+ render();
+
+}
+
+function hide0() {
+ var child = g_client.root.children[1];
+ child.visible = !child.visible;
+ render();
+}
+
+function hide1() {
+ var child = g_client.root.children[2];
+ child.visible = !child.visible;
+ render();
+}
+
+function reportError(msg) {
+ g_errorMsgElement.innerHTML = g_client.lastError;
+ g_client.clearLastError();
+ g_client.clearErrorCallback();
+}
+
+function render() {
+ // Render once now that things are setup.
+ g_client.setErrorCallback(reportError);
+ g_client.render();
+}
+
+function onRender() {
+}
+
+/**
+ * Removes any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ g_client.cleanup();
+}
+</script>
+</head>
+<body>
+<h1>Error Texture.</h1>
+<br/>
+Demonstrates how missing textures are handled.
+<div>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 800px; height: 600px;"></div>
+<!-- End of O3D plugin -->
+</div>
+<br/>
+<input type="button" value="User Texture" onClick="setToUserTexture()"/>
+<input type="button" value="No Texture" onClick="setToNoTexture()"/>
+<input type="button" value="hide 0" onClick="hide0()"/>
+<input type="button" value="hide 1" onClick="hide1()"/>
+<table><tr><td>Error: </td><td id="errorMsg">-</td></tr></table>
+</html>
diff --git a/o3d/samples/o3d-webgl/base.js b/o3d/samples/o3d-webgl/base.js
index ba23128..ce46219 100644
--- a/o3d/samples/o3d-webgl/base.js
+++ b/o3d/samples/o3d-webgl/base.js
@@ -234,6 +234,7 @@ o3d.include('object_base');
o3d.include('named_object_base');
o3d.include('named_object');
o3d.include('param_object');
+o3d.include('param_array');
o3d.include('param');
o3d.include('event');
o3d.include('raw_data');
diff --git a/o3d/samples/o3d-webgl/client.js b/o3d/samples/o3d-webgl/client.js
index 798ffe3..ebb28f4 100644
--- a/o3d/samples/o3d-webgl/client.js
+++ b/o3d/samples/o3d-webgl/client.js
@@ -652,6 +652,31 @@ o3d.Client.prototype.initWithCanvas = function(canvas) {
height: canvas.height};
o3d.State.createDefaultState_(gl).push_();
+ // Create the default error texture.
+ var defaultTexture = new o3d.Texture2D();
+ defaultTexture.gl = this.gl;
+ defaultTexture.init_(8, 8, o3d.Texture.ARGB8, 1, false);
+ var r = [1, 0, 0, 1];
+ var Y = [1, 1, 0, 1];
+ var error = [r, r, r, r, r, r, r, r,
+ r, r, Y, Y, Y, Y, r, r,
+ r, Y, r, r, r, Y, Y, r,
+ r, Y, r, r, Y, r, Y, r,
+ r, Y, r, Y, r, r, Y, r,
+ r, Y, Y, r, r, r, Y, r,
+ r, r, Y, Y, Y, Y, r, r,
+ r, r, r, r, r, r, r, r];
+ var pixels = [];
+ for (var i = 0; i < error.length; i++) {
+ for (var j = 0; j < 4; j++) {
+ pixels[i * 4 + j] = error[i][j];
+ }
+ }
+ defaultTexture.set(0, pixels);
+ defaultTexture.name = 'DefaultTexture';
+ this.fallback_error_texture_ = defaultTexture;
+ this.error_texture_ = defaultTexture;
+
return true;
};
@@ -917,7 +942,7 @@ o3d.Client.prototype.clearEventCallback =
*/
o3d.Client.prototype.setErrorTexture =
function(texture) {
- o3d.notImplemented();
+ this.error_texture_ = texture;
};
@@ -978,14 +1003,32 @@ o3d.Client.prototype.setErrorCallback =
function(error_callback) {
// Other code expects to not see a null error callback.
if (error_callback) {
- this.error_callback = error_callback;
+ this.error_callback = this.wrapErrorCallback_(error_callback);
} else {
- this.error_callback = function(string) {};
+ this.error_callback = function(string) {
+ this.last_error_ = string;
+ };
}
};
/**
+ * Wraps a callback function, saving the error string so that the
+ * lastError variable can access it.
+ *
+ * @param {function} error_callback User-defined error callback.
+ * @return {function} Wrapped error callback.
+ * @private
+ */
+o3d.Client.prototype.wrapErrorCallback_ = function(error_callback) {
+ return function(string) {
+ this.last_error_ = string;
+ error_callback(string);
+ }
+}
+
+
+/**
* Clears the Error callback
*
* NOTE: The client takes ownership of the ErrorCallback you
@@ -1102,7 +1145,6 @@ o3d.Client.prototype.getState_ = function(name) {
o3d.Client.prototype.renderer_init_status = 0;
-
/**
* Gets / Sets the cursor's shape.
*
@@ -1112,12 +1154,49 @@ o3d.Client.prototype.cursor = null;
/**
+ * The current error texture.
+ *
+ * @type {o3d.Texture}
+ * @private
+ */
+o3d.Client.prototype.error_texture_ = null;
+
+
+/**
+ * The fallback error texture. Should only be initialized once per client and
+ * is read-only.
+ *
+ * @type {!o3d.Texture}
+ * @private
+ */
+o3d.Client.prototype.fallback_error_texture_ = null;
+
+
+/**
* The last error reported by the plugin.
*
* @type {string}
+ * @private
*/
o3d.Client.prototype.last_error_ = '';
+o3d.Client.prototype.__defineGetter__('lastError',
+ function() {
+ return this.last_error_;
+ }
+);
+/**
+ * Returns true if missing textures, samplers or ParamSamplers should be
+ * reported by calling the error callback. We assume that if the user
+ * explicitly sets the error texture to null, then they want such errors to
+ * trigger the error callback.
+ *
+ * @return {boolean}
+ * @private
+ */
+o3d.Client.prototype.reportErrors_ = function() {
+ return (this.error_texture_ == null);
+}
/**
@@ -1146,7 +1225,7 @@ o3d.Client.prototype.objects = [];
* Clears the error returned in lastError.
*/
o3d.Client.prototype.clearLastError = function () {
- o3d.notImplemented();
+ this.last_error_ = '';
};
@@ -1190,5 +1269,3 @@ o3d.Client.prototype.clientInfo = null;
* @type {Element}
*/
o3d.Client.prototype.canvas = null;
-
-
diff --git a/o3d/samples/o3d-webgl/effect.js b/o3d/samples/o3d-webgl/effect.js
index 4d10b72..93932b0 100644
--- a/o3d/samples/o3d-webgl/effect.js
+++ b/o3d/samples/o3d-webgl/effect.js
@@ -62,9 +62,9 @@ o3d.EffectParameterInfo =
/**
* The semantic of the parameter. This is always in UPPERCASE.
- * @type {o3d.Stream.Semantic}
+ * @type {string}
*/
- this.semantic = semantic || o3d.Stream.UNKNOWN_SEMANTIC;
+ this.semantic = semantic || '';
/**
* If this is a standard parameter (SAS) this will be the name of the type
@@ -266,6 +266,24 @@ o3d.Effect.prototype.loadFromFXString =
/**
+ * Generates an array of indexed strings. For example, given 'arr' and a size
+ * of 10, generates 'arr[0]', 'arr[1]', 'arr[2]' up to 'arr[9]'.
+ *
+ * @param {string} base The name of the array.
+ * @param {number} size The number of elements in the array.
+ * @return {!Array.<string>}
+ * @private
+ */
+o3d.Effect.prototype.getParamArrayNames_ = function(base, size) {
+ var names = [];
+ for (var i = 0; i < size; i++) {
+ names[i] = base + '[' + i + ']';
+ }
+ return names;
+}
+
+
+/**
* Iterates through the active uniforms of the program and gets the
* location of each one and stores them by name in the uniforms
* object.
@@ -278,8 +296,28 @@ o3d.Effect.prototype.getUniforms_ =
this.program_, this.gl.ACTIVE_UNIFORMS);
for (var i = 0; i < numUniforms; ++i) {
var info = this.gl.getActiveUniform(this.program_, i);
- this.uniforms_[info.name] = {info: info,
- location: this.gl.getUniformLocation(this.program_, info.name)};
+ if (info.name.indexOf('[') != -1) {
+ // This is an array param and we need to individually query each item in
+ // the array to get its location.
+ var baseName = info.name.substring(0, info.name.indexOf('['));
+ var names = this.getParamArrayNames_(baseName, info.size);
+ var locations = [];
+ for (var j = 0; j < names.length; j++) {
+ locations[j] = this.gl.getUniformLocation(this.program_, names[j]);
+ }
+ this.uniforms_[baseName] = {
+ info: {name: baseName, size: info.size, type: info.type},
+ kind: o3d.Effect.ARRAY,
+ locations: locations /* mind the s */
+ };
+ } else {
+ // Not an array param.
+ this.uniforms_[info.name] = {
+ info: info,
+ kind: o3d.Effect.ELEMENT,
+ location: this.gl.getUniformLocation(this.program_, info.name)
+ };
+ }
}
};
@@ -334,6 +372,7 @@ o3d.Effect.getParamTypes_ = function(gl) {
return o3d.Effect.paramTypes_;
}
+
/**
* A map linking names of certain attributes in the shader to the corresponding
* semantic and semantic index.
@@ -375,11 +414,21 @@ o3d.Effect.prototype.createUniformParameters =
function(param_object) {
var sasTypes = o3d.Param.sasTypes_;
var paramTypes = o3d.Effect.getParamTypes_(this.gl);
-
for (var name in this.uniforms_) {
- var info = this.uniforms_[name].info;
+ var uniformData = this.uniforms_[name];
if (!sasTypes[name]) {
- param_object.createParam(info.name, paramTypes[info.type]);
+ switch (uniformData.kind) {
+ case o3d.Effect.ARRAY:
+ param_object.createParam(name, 'ParamParamArray');
+ break;
+ case o3d.Effect.STRUCT:
+ o3d.notImplemented();
+ break;
+ case o3d.Effect.ELEMENT:
+ default:
+ param_object.createParam(name, paramTypes[uniformData.info.type]);
+ break;
+ }
}
}
};
@@ -422,19 +471,18 @@ o3d.Effect.prototype.createSASParameters =
o3d.Effect.prototype.getParameterInfo = function() {
var infoArray = [];
var sasTypes = o3d.Param.sasTypes_;
- var paramTypes = o3d.Effect.getParamTypes_(this.gl);
var semanticMap = o3d.Effect.semanticMap_;
+ var paramTypes = o3d.Effect.getParamTypes_(this.gl);
for (var name in this.uniforms_) {
- var info = this.uniforms_[name].info;
- var sasTypeName = sasTypes[name] || '';
- var className = paramTypes[info.type] || '';
- var numElements = 0; // TODO(petersont): Add array support.
- var semantic = (semanticMap[name] && semanticMap[name].semantic) ?
- semanticMap[name].semantic : o3d.Stream.UNKNOWN_SEMANTIC;
-
+ var uniformData = this.uniforms_[name];
+ var sasClassName = sasTypes[name] || '';
+ var dataType = paramTypes[uniformData.info.type] || '';
+ var numElements = (uniformData.kind == o3d.Effect.ARRAY) ?
+ uniformData.info.size : 0; // 0 if a non-array type.
+ var semantic = semanticMap[name] ? name : '';
infoArray.push(new o3d.EffectParameterInfo(
- name, className, numElements, semantic, sasTypeName));
+ name, dataType, numElements, semantic.toUpperCase(), sasClassName));
}
return infoArray;
@@ -461,7 +509,7 @@ o3d.Effect.prototype.getStreamInfo = function() {
/**
* Searches the objects in the given list for parameters to apply to the
* uniforms defined on this effects program, and applies them, favoring
- * the objects nearer the begining of the list.
+ * the objects nearer the beginning of the list.
*
* @param {!Array.<!o3d.ParamObject>} object_list The param objects to search.
* @private
@@ -482,7 +530,11 @@ o3d.Effect.prototype.searchForParams_ = function(object_list) {
}
var param = obj.getParam(name);
if (param) {
- param.applyToLocation(this.gl, uniformInfo.location);
+ if (uniformInfo.kind == o3d.Effect.ARRAY) {
+ param.applyToLocations(this.gl, uniformInfo.locations);
+ } else {
+ param.applyToLocation(this.gl, uniformInfo.location);
+ }
filled_map[name] = true;
}
}
@@ -491,10 +543,19 @@ o3d.Effect.prototype.searchForParams_ = function(object_list) {
this.updateHelperConstants_(this.gl.displayInfo.width,
this.gl.displayInfo.height);
filled_map[o3d.Effect.HELPER_CONSTANT_NAME] = true;
-
for (var name in this.uniforms_) {
if (!filled_map[name]) {
- throw ('Uniform param not filled: "'+ name + '"');
+ if (this.uniforms_[name].info.type == this.gl.SAMPLER_2D) {
+ if (this.gl.client.reportErrors_()) {
+ this.gl.client.error_callback("Missing ParamSampler");
+ }
+ var defaultParamSampler = o3d.ParamSampler.defaultParamSampler_;
+ defaultParamSampler.gl = this.gl;
+ defaultParamSampler.applyToLocation(this.gl,
+ this.uniforms_[name].location);
+ } else {
+ throw ('Uniform param not filled: "'+ name + '"');
+ }
}
}
};
@@ -543,6 +604,17 @@ o3d.Effect.COLUMN_MAJOR = 1;
/**
+ * UniformType,
+ * ELEMENT, the param is a single gl.* element
+ * ARRAY, the param is an array of same-typed elements
+ * STRUCT, not implemented
+ */
+o3d.Effect.ELEMENT = 0;
+o3d.Effect.ARRAY = 1;
+o3d.Effect.STRUCT = 2;
+
+
+/**
* The order in which matrix data is loaded to the GPU.
* @type {o3d.Effect.MatrixLoadOrder}
*/
@@ -554,5 +626,3 @@ o3d.Effect.prototype.matrix_load_order_ = o3d.Effect.ROW_MAJOR;
* @type {string}
*/
o3d.Effect.prototype.source_ = '';
-
-
diff --git a/o3d/samples/o3d-webgl/param.js b/o3d/samples/o3d-webgl/param.js
index 59c0219..1aae87e 100644
--- a/o3d/samples/o3d-webgl/param.js
+++ b/o3d/samples/o3d-webgl/param.js
@@ -337,7 +337,7 @@ o3d.inherit('ParamMatrix4', 'Param');
*/
o3d.ParamParamArray = function() {
o3d.Param.call(this);
- this.value = [];
+ this.value = null;
};
o3d.inherit('ParamParamArray', 'Param');
@@ -834,6 +834,23 @@ o3d.ParamMatrix4.prototype.applyToLocation = function(gl, location) {
};
/**
+ * Called to specify the values of a uniform array.
+ * @param {WebGLContext} gl The current context.
+ * @param {!Array.<!WebGLUniformLocation>} locationArray An array of locations
+ * to which to apply the values.
+ */
+o3d.ParamParamArray.prototype.applyToLocations = function(gl, locationArray) {
+ if (locationArray.length != this.value.length) {
+ gl.client.error_callback(
+ 'Invalid uniform param array: incorrect number of elements.');
+ }
+ for (var i = 0; i < this.value.length; i++) {
+ // Cannot have a ParamArray of ParamArrays, so safe to call applyToLocation
+ this.value.getParam(i).applyToLocation(gl, locationArray[i]);
+ }
+};
+
+/**
* A counter to ensure each texture sampler gets a unqiue id.
* @private
*/
@@ -852,14 +869,30 @@ o3d.ParamSampler.prototype.applyToLocation = function(gl, location) {
var value = null;
var target = 0;
+ var sampler = null;
if (this.value) {
- this.value.bindAndSetParameters_();
- gl.uniform1i(location, i);
- o3d.Param.texture_index_++;
+ sampler = this.value;
+ } else {
+ o3d.Sampler.defaultSampler_.gl = gl;
+ sampler = o3d.Sampler.defaultSampler_;
+ if (gl.client.reportErrors_()) {
+ gl.client.error_callback("Missing Sampler for ParamSampler " + this.name);
+ }
}
+
+ sampler.bindAndSetParameters_();
+ gl.uniform1i(location, i);
+ o3d.Param.texture_index_++;
};
+/**
+ * A default ParamSampler to be used if client does not assign one.
+ *
+ * @type {!o3d.ParamSampler}
+ * @private
+ */
+o3d.ParamSampler.defaultParamSampler_ = new o3d.ParamSampler();
/**
* Object to compute all combinations of world/view/projection
diff --git a/o3d/samples/o3d-webgl/param_array.js b/o3d/samples/o3d-webgl/param_array.js
new file mode 100644
index 0000000..236c45a
--- /dev/null
+++ b/o3d/samples/o3d-webgl/param_array.js
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * A ParamArray is an object that holds an array of Params.
+ * @constructor
+ */
+o3d.ParamArray = function() {
+ o3d.NamedObject.call(this);
+ this.params_ = [];
+};
+o3d.inherit('ParamArray', 'NamedObject');
+
+
+/**
+ * Creates a Param of the given type at the index requested. If a Param already
+ * exists at that index the new param will be replace it. If the index is past
+ * the end of the current array params of the requested type will be created to
+ * fill out the array to the requested index.
+ *
+ * @param {number} index Index at which to create new param.
+ * @param {string} param_type_name The type of Param to create. For a list of
+ * valid types see ParamObject.createParam
+ * @return {!o3d.ParamArray} The newly created Param or null if failure.
+ */
+o3d.ParamArray.prototype.createParam = function(index, param_type_name) {
+ param_type_name = o3d.filterTypeName_(param_type_name);
+ if (!o3d.global.o3d[param_type_name])
+ throw ('Invalid param type name: ' + param_type_name);
+ if (index >= this.params_.length) {
+ this.resize(index + 1, param_type_name);
+ } else {
+ var param = new o3d.global.o3d[param_type_name];
+ param.gl = this.gl;
+ param.owner_ = this;
+ this.params_[index] = param;
+ }
+
+ return this.filterResult_(this.params_[index]);
+};
+
+
+/**
+ * Gets a Param by index.
+ *
+ * @param {number} index Index of Param to get.
+ * @return {!o3d.Param} The Param at index, or null if out of range.
+ */
+o3d.ParamArray.prototype.getParam = function(index) {
+ var result = this.params_[index];
+ return this.filterResult_(result);
+};
+
+
+/**
+ * Removes a range of params. This shrinks the array and affects the indices of
+ * later occurring items.
+ *
+ * @param {number} start_index Index of first param to remove.
+ * @param {number} num_to_remove The number of params to remove starting at
+ * start_index.
+ */
+o3d.ParamArray.prototype.removeParams = function(start_index, num_to_remove) {
+ var paramsNew = [];
+ var j = 0;
+ for (var i = 0; i < this.params_.length; i++) {
+ if (i >= start_index && i < start_index + num_to_remove) {
+ // Skip these to remove them.
+ } else {
+ paramsNew[j] = this.params_[i];
+ j++;
+ }
+ }
+ this.params_ = paramsNew;
+};
+
+
+/**
+ * Resizes the array.
+ *
+ * @param {number} num_params The number of params to make the array.
+ * @param {string} param_type_name The type of Param to create if resizing
+ * requires params to be created. For a list of valid types see
+ * ParamObject.createParam.
+ */
+o3d.ParamArray.prototype.resize = function(num_params, param_type_name) {
+ param_type_name = o3d.filterTypeName_(param_type_name);
+ if (!o3d.global.o3d[param_type_name])
+ throw ('Invalid param type name: ' + param_type_name);
+
+ for (var i = this.params_.length; i < num_params; i++) {
+ var param = new o3d.global.o3d[param_type_name];
+ param.gl = this.gl;
+ param.owner_ = this;
+ this.params_[i] = param;
+ }
+};
+
+/**
+ * The params stored in this ParamArray.
+ *
+ * @type {!Array.<!o3d.Param>}
+ * @private
+ */
+o3d.ParamArray.prototype.params_ = [];
+
+/**
+ * Gets all the param on this param object.
+ *
+ * Each access to this field gets the entire list, so it is best to get it
+ * just once. For example:
+ *
+ * var params = ParamArray.params;
+ * for (var i = 0; i < params.length; i++) {
+ * var param = params[i];
+ * }
+ *
+ * Note that modifications to this array [e.g. push()] will not affect
+ * the underlying ParamArray, while modifications to the array's members
+ * <b>will</b> affect them.
+ *
+ * @type {!Array.<!o3d.Param>}
+ */
+o3d.ParamArray.prototype.__defineGetter__('params',
+ function() {
+ var params = [];
+ for (var i = 0; i < this.length; i++) {
+ params[i] = this.params_[i];
+ }
+ return params;
+ }
+);
+
+
+/**
+ * Returns the number of parameters in this ParamArray.
+ *
+ * @type {number}
+ */
+o3d.ParamArray.prototype.__defineGetter__('length',
+ function() {
+ return this.params_.length;
+ }
+);
+
+
+/**
+ * Filters results, turning 'undefined' into 'null'.
+ *
+ * @param {*} result
+ * @private
+ */
+o3d.ParamArray.prototype.filterResult_= function(result) {
+ return (result ? result : null);
+};
diff --git a/o3d/samples/o3d-webgl/param_object.js b/o3d/samples/o3d-webgl/param_object.js
index 78ee725..61f3fac 100644
--- a/o3d/samples/o3d-webgl/param_object.js
+++ b/o3d/samples/o3d-webgl/param_object.js
@@ -109,6 +109,7 @@ o3d.ParamObject.prototype.createParam =
var param = new o3d.global.o3d[param_type_name];
param.gl = this.gl;
param.owner_ = this;
+ param.name = param_name;
this.params_[param_name] = param;
return this.filterResult_(this.params_[param_name]);
};
diff --git a/o3d/samples/o3d-webgl/sampler.js b/o3d/samples/o3d-webgl/sampler.js
index eb0a0e1..4e651a9 100644
--- a/o3d/samples/o3d-webgl/sampler.js
+++ b/o3d/samples/o3d-webgl/sampler.js
@@ -250,24 +250,37 @@ o3d.Sampler.prototype.convertMagFilter_ = function(o3d_filter) {
/**
+ * A default Sampler that has no texture, thus uses the client's error texture.
+ *
+ * @type {!o3d.Sampler}
+ * @private
+ */
+o3d.Sampler.defaultSampler_ = new o3d.Sampler();
+o3d.Sampler.defaultSampler_.magFilter = o3d.Sampler.POINT;
+
+/**
* Binds the texture for this sampler and sets texParameters according to the
* states of the sampler.
*/
o3d.Sampler.prototype.bindAndSetParameters_ = function() {
+ var currentTexture = null;
if (this.texture) {
- var mip_filter = this.mipFilter;
- if (this.texture.levels == 1) {
- mip_filter = o3d.Sampler.NONE;
- }
-
- this.texture.bindAndSetParameters_(
- this.convertAddressMode_(this.addressModeU),
- this.convertAddressMode_(this.addressModeV),
- this.convertMinFilter_(this.minFilter, mip_filter),
- this.convertMagFilter_(this.magFilter));
+ currentTexture = this.texture;
+ } else if (!this.gl.client.reportErrors_()) {
+ currentTexture = this.gl.client.error_texture_;
} else {
- this.gl.client.error_callback("Sampler used with no texture set.");
- return;
+ currentTexture = this.gl.client.fallback_error_texture_;
+ this.gl.client.error_callback("Missing texture for sampler " + this.name);
+ }
+
+ var mip_filter = this.mipFilter;
+ if (currentTexture.levels == 1) {
+ mip_filter = o3d.Sampler.NONE;
}
+ currentTexture.bindAndSetParameters_(
+ this.convertAddressMode_(this.addressModeU),
+ this.convertAddressMode_(this.addressModeV),
+ this.convertMinFilter_(this.minFilter, mip_filter),
+ this.convertMagFilter_(this.magFilter));
}
diff --git a/o3d/samples/o3djs/effect.js b/o3d/samples/o3djs/effect.js
index 0d23889..c9b5548 100644
--- a/o3d/samples/o3djs/effect.js
+++ b/o3d/samples/o3djs/effect.js
@@ -617,16 +617,16 @@ o3djs.effect.buildCheckerShaderString = function() {
var p = o3djs.effect;
var varyingDecls = p.BEGIN_OUT_STRUCT +
p.VARYING + p.FLOAT4 + ' ' +
- p.VERTEX_VARYING_PREFIX + 'position' +
+ p.VARYING_DECLARATION_PREFIX + 'position' +
p.semanticSuffix('POSITION') + ';\n' +
p.VARYING + p.FLOAT2 + ' ' +
- p.VERTEX_VARYING_PREFIX + 'texCoord' +
+ p.VARYING_DECLARATION_PREFIX + 'texCoord' +
p.semanticSuffix('TEXCOORD0') + ';\n' +
p.VARYING + p.FLOAT3 + ' ' +
- p.VERTEX_VARYING_PREFIX + 'normal' +
+ p.VARYING_DECLARATION_PREFIX + 'normal' +
p.semanticSuffix('TEXCOORD1') + ';\n' +
p.VARYING + p.FLOAT3 + ' ' +
- p.VERTEX_VARYING_PREFIX + 'worldPosition' +
+ p.VARYING_DECLARATION_PREFIX + 'worldPosition' +
p.semanticSuffix('TEXCOORD2') + ';\n' +
p.END_STRUCT;