| Index: samples/o3djs/gpu2d.js
|
| ===================================================================
|
| --- samples/o3djs/gpu2d.js (revision 0)
|
| +++ samples/o3djs/gpu2d.js (revision 0)
|
| @@ -0,0 +1,680 @@
|
| +/*
|
| + * 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.
|
| + */
|
| +
|
| +
|
| +/**
|
| + * @fileoverview This file provides GPU-accelerated rendering of 2D
|
| + * vector graphics in 3D.
|
| + */
|
| +o3djs.provide('o3djs.gpu2d');
|
| +
|
| +/**
|
| + * A module providing GPU-accelerated rendering of 2D vector graphics
|
| + * in 3D.
|
| + * @namespace
|
| + */
|
| +o3djs.gpu2d = o3djs.gpu2d || {};
|
| +
|
| +/**
|
| + * Creates a new Path, which holds one or more closed contours
|
| + * composed of 2D primitives like lines, quadratic curves, and cubic
|
| + * curves.
|
| + * @param {!o3d.Pack} pack Pack in which geometry and materials
|
| + * associated with the curves will be created.
|
| + * @param {!o3d.DrawList} drawList The DrawList on which the triangle
|
| + * mesh will be drawn. Typically this will be the
|
| + * zOrderedDrawList from an o3djs.rendergraph.ViewInfo.
|
| + * @return {!o3djs.gpu2d.Path} The created Path.
|
| + */
|
| +o3djs.gpu2d.createPath = function(pack,
|
| + drawList) {
|
| + return new o3djs.gpu2d.Path(pack, drawList);
|
| +};
|
| +
|
| +/**
|
| + * Constructs a new Path. Do not call this directly; use
|
| + * o3djs.gpu2d.createPath instead.
|
| + * @param {!o3d.Pack} pack Pack in which geometry and materials
|
| + * associated with the curves will be created.
|
| + * @param {!o3d.DrawList} drawList The DrawList on which the triangle
|
| + * mesh will be drawn. Typically this will be the
|
| + * zOrderedDrawList.
|
| + * @constructor
|
| + */
|
| +o3djs.gpu2d.Path = function(pack, drawList) {
|
| + /**
|
| + * Pack in which curves' geometry and materials are created.
|
| + * @type {!o3d.Pack}
|
| + * @private
|
| + */
|
| + this.pack_ = pack;
|
| +
|
| + /**
|
| + * DrawList in which curves' geometry and materials will be
|
| + * rendered.
|
| + * @type {!o3d.DrawList}
|
| + * @private
|
| + */
|
| + this.drawList_ = drawList;
|
| +
|
| + /**
|
| + * Internal object which manages the triangle mesh associated with
|
| + * the curves.
|
| + * @type {!o3d.ProcessedPath}
|
| + * @private
|
| + */
|
| + this.path_ = pack.createObject('ProcessedPath');
|
| +
|
| + // Set up the Primitives in the ProcessedPath.
|
| + //
|
| + // The mesh is separated into two different regions. The exterior
|
| + // region of the mesh is the portion containing the cubic curve
|
| + // segments. It is this region whose alpha value is computed using
|
| + // Loop and Blinn's shader. The interior region of the mesh is
|
| + // simply filled with a constant alpha. The reason for the split is
|
| + // that it is difficult to assign texture coordinates to cause Loop
|
| + // and Blinn's shader to fill a region with constant alpha. While
|
| + // there is some cost associated with switching shaders and
|
| + // performing two draw calls, doing so simplifies the logic.
|
| +
|
| + // Create state objects so we can turn on alpha blending for the
|
| + // exterior triangles. We also disable backface culling so that we
|
| + // can view the vector shapes from both sides.
|
| + var exteriorState = pack.createObject('State');
|
| + exteriorState.getStateParam('o3d.AlphaBlendEnable').value = true;
|
| + exteriorState.getStateParam('o3d.SourceBlendFunction').value =
|
| + o3djs.base.o3d.State.BLENDFUNC_SOURCE_ALPHA;
|
| + exteriorState.getStateParam('o3d.DestinationBlendFunction').value =
|
| + o3djs.base.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA;
|
| + exteriorState.getStateParam('o3d.CullMode').value =
|
| + o3djs.base.o3d.State.CULL_NONE;
|
| +
|
| + var interiorState = pack.createObject('State');
|
| + interiorState.getStateParam('o3d.CullMode').value =
|
| + o3djs.base.o3d.State.CULL_NONE;
|
| +
|
| + // Create the materials for the exterior and interior regions.
|
| +
|
| + /**
|
| + * The material for the exterior triangles, filled with Loop and
|
| + * Blinn's shader.
|
| + * @type {!o3d.Material}
|
| + * @private
|
| + */
|
| + this.exteriorMaterial_ = pack.createObject('Material');
|
| + this.exteriorMaterial_.name = 'ExteriorMaterial';
|
| + this.exteriorMaterial_.state = exteriorState;
|
| + this.exteriorMaterial_.drawList = drawList;
|
| +
|
| + /**
|
| + * The material for the interior triangles, filled with a solid
|
| + * shader.
|
| + * @type {!o3d.Material}
|
| + * @private
|
| + */
|
| + this.interiorMaterial_ = pack.createObject('Material');
|
| + this.interiorMaterial_.name = 'InteriorMaterial';
|
| + this.interiorMaterial_.state = interiorState;
|
| + this.interiorMaterial_.drawList = drawList;
|
| +
|
| + /**
|
| + * The Shape which is the transform graph's view of the Path.
|
| + * @type {!o3d.Shape}
|
| + */
|
| + this.shape = pack.createObject('Shape');
|
| +
|
| + // Create the exterior region.
|
| + var primitive = pack.createObject('Primitive');
|
| + var streamBank = pack.createObject('StreamBank');
|
| + var vertexBuffer = pack.createObject('VertexBuffer');
|
| + // The coordinates of the triangles are 2D
|
| + var vertices = vertexBuffer.createField('FloatField', 2);
|
| + /**
|
| + * The Field for the exterior vertices.
|
| + * @type {!o3d.FloatField}
|
| + * @private
|
| + */
|
| + this.exteriorVertices_ = vertices;
|
| + // The (Loop/Blinn) texture coordinates are 3D
|
| + var texcoords = vertexBuffer.createField('FloatField', 3);
|
| + /**
|
| + * The Field for the exterior texture coordinates.
|
| + * @type {!o3d.FloatField}
|
| + * @private
|
| + */
|
| + this.exteriorTexCoords_ = texcoords;
|
| + streamBank.setVertexStream(o3djs.base.o3d.Stream.POSITION, 0, vertices, 0);
|
| + streamBank.setVertexStream(o3djs.base.o3d.Stream.TEXCOORD, 0, texcoords, 0);
|
| + primitive.streamBank = streamBank;
|
| + primitive.primitiveType = o3djs.base.o3d.Primitive.TRIANGLELIST;
|
| + primitive.material = this.exteriorMaterial_;
|
| + primitive.owner = this.shape;
|
| + /**
|
| + * The Primitive for the exterior triangles.
|
| + * @type {!o3d.Primitive}
|
| + * @private
|
| + */
|
| + this.exteriorTriangles_ = primitive;
|
| +
|
| + // Create the interior region.
|
| + primitive = pack.createObject('Primitive');
|
| + streamBank = pack.createObject('StreamBank');
|
| + vertexBuffer = pack.createObject('VertexBuffer');
|
| + // The coordinates of the triangles are 2D
|
| + vertices = vertexBuffer.createField('FloatField', 2);
|
| + /**
|
| + * The Field for the interior vertices.
|
| + * @type {!o3d.FloatField}
|
| + * @private
|
| + */
|
| + this.interiorVertices_ = vertices;
|
| + streamBank.setVertexStream(o3djs.base.o3d.Stream.POSITION, 0, vertices, 0);
|
| + primitive.streamBank = streamBank;
|
| + primitive.primitiveType = o3djs.base.o3d.Primitive.TRIANGLELIST;
|
| + primitive.material = this.interiorMaterial_;
|
| + primitive.owner = this.shape;
|
| + /**
|
| + * The Primitive for the interior triangles.
|
| + * @type {!o3d.Primitive}
|
| + * @private
|
| + */
|
| + this.interiorTriangles_ = primitive;
|
| +
|
| + // Initialize the fill to a solid color.
|
| + this.setFill(o3djs.gpu2d.createColor(pack, 0.0, 0.0, 0.0, 1.0));
|
| +
|
| + // Create draw elements for the shape.
|
| + this.shape.createDrawElements(pack, null);
|
| +};
|
| +
|
| +/**
|
| + * Clears out any previously added segments or generated triangles
|
| + * from this Path.
|
| + */
|
| +o3djs.gpu2d.Path.prototype.clear = function() {
|
| + this.path_.clear();
|
| +};
|
| +
|
| +/**
|
| + * Moves the pen to the given absolute X,Y coordinates. If a contour
|
| + * isn't currently open on this path, one is opened.
|
| + * @param {number} x the x coordinate to move to.
|
| + * @param {number} y the y coordinate to move to.
|
| + */
|
| +o3djs.gpu2d.Path.prototype.moveTo = function(x, y) {
|
| + this.path_.moveTo(x, y);
|
| +};
|
| +
|
| +/**
|
| + * Draws a line from the current coordinates to the given absolute
|
| + * X,Y coordinates.
|
| + * @param {number} x the x coordinate to draw a line to.
|
| + * @param {number} y the y coordinate to draw a line to.
|
| + */
|
| +o3djs.gpu2d.Path.prototype.lineTo = function(x, y) {
|
| + this.path_.lineTo(x, y);
|
| +};
|
| +
|
| +/**
|
| + * Draws a quadratic curve from the current coordinates through the
|
| + * given control point and end point, specified in absolute
|
| + * coordinates.
|
| + * @param {number} cx the x coordinate of the quadratic's control point
|
| + * @param {number} cy the y coordinate of the quadratic's control point
|
| + * @param {number} x the x coordinate of the quadratic's end point
|
| + * @param {number} y the y coordinate of the quadratic's end point
|
| + */
|
| +o3djs.gpu2d.Path.prototype.quadraticTo = function(cx, cy, x, y) {
|
| + this.path_.quadraticTo(cx, cy, x, y);
|
| +};
|
| +
|
| +/**
|
| + * Draws a cubic curve from the current coordinates through the
|
| + * given control points and end point, specified in absolute
|
| + * coordinates.
|
| + * @param {number} c0x the x coordinate of the cubic's first control point
|
| + * @param {number} c0y the y coordinate of the cubic's first control point
|
| + * @param {number} c1x the x coordinate of the cubic's second control point
|
| + * @param {number} c1y the y coordinate of the cubic's second control point
|
| + * @param {number} x the x coordinate of the cubic's end point
|
| + * @param {number} y the y coordinate of the cubic's end point
|
| + */
|
| +o3djs.gpu2d.Path.prototype.cubicTo = function(c0x, c0y, c1x, c1y, x, y) {
|
| + this.path_.cubicTo(c0x, c0y, c1x, c1y, x, y);
|
| +};
|
| +
|
| +/**
|
| + * Closes the current contour on this Path.
|
| + */
|
| +o3djs.gpu2d.Path.prototype.close = function() {
|
| + this.path_.close();
|
| +};
|
| +
|
| +/**
|
| + * Updates the triangle mesh associated with this Path. Call this
|
| + * after adding any new segments to the Path.
|
| + */
|
| +o3djs.gpu2d.Path.prototype.update = function() {
|
| + this.path_.createMesh(this.exteriorVertices_,
|
| + this.exteriorTexCoords_,
|
| + this.interiorVertices_);
|
| + var numVertices = this.exteriorVertices_.buffer.numElements;
|
| + if (numVertices == 1) {
|
| + this.exteriorTriangles_.numberVertices = 0;
|
| + this.exteriorTriangles_.numberPrimitives = 0;
|
| + } else {
|
| + this.exteriorTriangles_.numberVertices = numVertices;
|
| + this.exteriorTriangles_.numberPrimitives = numVertices / 3;
|
| + }
|
| + numVertices = this.interiorVertices_.buffer.numElements;
|
| + if (numVertices == 1) {
|
| + this.interiorTriangles_.numberVertices = 0;
|
| + this.interiorTriangles_.numberPrimitives = 0;
|
| + } else {
|
| + this.interiorTriangles_.numberVertices = numVertices;
|
| + this.interiorTriangles_.numberPrimitives = numVertices / 3;
|
| + }
|
| +};
|
| +
|
| +//----------------------------------------------------------------------
|
| +// Fills
|
| +
|
| +/**
|
| + * Sets the fill for this Path.
|
| + * @param {!o3djs.gpu2d.Fill} fill the fill for this Path.
|
| + */
|
| +o3djs.gpu2d.Path.prototype.setFill = function(fill) {
|
| + if (this.fill_) {
|
| + this.fill_.detach_(this);
|
| + }
|
| + this.interiorMaterial_.effect = fill.interiorEffect;
|
| + this.exteriorMaterial_.effect = fill.exteriorEffect;
|
| + this.fill_ = fill;
|
| + fill.attach_(this);
|
| +};
|
| +
|
| +/**
|
| + * Base class for all Fills. Do not call this directly; use, for
|
| + * example, o3djs.gpu2d.createColor instead.
|
| + * @param {!o3d.Pack} pack the Pack in which to create materials.
|
| + * @constructor
|
| + */
|
| +o3djs.gpu2d.Fill = function(pack) {
|
| + this.pack_ = pack;
|
| + this.attachedPaths_ = [];
|
| +};
|
| +
|
| +/**
|
| + * Attaches this Fill to the given path.
|
| + * @param {!o3djs.gpu2d.Path} path Path to attach the fill to.
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.Fill.prototype.attach_ = function(path) {
|
| + if (this.attachedPaths_.indexOf(path) < 0)
|
| + this.attachedPaths_.push(path);
|
| + this.apply_(path);
|
| +};
|
| +
|
| +/**
|
| + * Detaches this Fill from the given path.
|
| + * @param {!o3djs.gpu2d.Path} path Path to detach the fill from.
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.Fill.prototype.detach_ = function(path) {
|
| + var idx = this.attachedPaths_.indexOf(path);
|
| + if (idx >= 0)
|
| + this.attachedPaths_.splice(idx, idx);
|
| +};
|
| +
|
| +/**
|
| + * Applies this Fill to all attached paths.
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.Fill.prototype.applyToPaths_ = function() {
|
| + for (var i = 0; i < this.attachedPaths_.length; i++) {
|
| + this.apply_(this.attachedPaths_[i]);
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * Base "apply" operation for fills -- a no-op.
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.Fill.prototype.apply_ = function(path) {
|
| +};
|
| +
|
| +/**
|
| + * A class for a solid color fill. Do not call this directly; use
|
| + * o3djs.gpu2d.createColor instead.
|
| + * @param {!o3d.Pack} pack the Pack in which to create materials.
|
| + * @constructor
|
| + * @extends {o3djs.gpu2d.Fill}
|
| + */
|
| +o3djs.gpu2d.Color = function(pack) {
|
| + o3djs.gpu2d.Fill.call(this, pack);
|
| + this.interiorEffect =
|
| + o3djs.gpu2d.loadEffect_(pack, o3djs.gpu2d.FillTypes_.COLOR, true);
|
| + this.exteriorEffect =
|
| + o3djs.gpu2d.loadEffect_(pack, o3djs.gpu2d.FillTypes_.COLOR, false);
|
| + this.r_ = 0.0;
|
| + this.g_ = 0.0;
|
| + this.b_ = 0.0;
|
| + this.a_ = 1.0;
|
| +};
|
| +
|
| +o3djs.base.inherit(o3djs.gpu2d.Color,
|
| + o3djs.gpu2d.Fill);
|
| +
|
| +/**
|
| + * Sets the color of this fill.
|
| + * @param {number} r Red component (0.0 - 1.0).
|
| + * @param {number} g Green component (0.0 - 1.0).
|
| + * @param {number} b Blue component (0.0 - 1.0).
|
| + * @param {number} a Alpha component (0.0 - 1.0).
|
| + */
|
| +o3djs.gpu2d.Color.prototype.set = function(r, g, b, a) {
|
| + this.r_ = r;
|
| + this.g_ = g;
|
| + this.b_ = b;
|
| + this.a_ = a;
|
| + this.applyToPaths_();
|
| +};
|
| +
|
| +/**
|
| + * Gets the value of the Color fill as an array.
|
| + * @return {!o3d.Float4}
|
| + */
|
| +o3djs.gpu2d.Color.prototype.get = function() {
|
| + return [this.r_, this.g_, this.b_, this.a_];
|
| +};
|
| +
|
| +/**
|
| + * Applies this color to the given path.
|
| + * @param {!o3djs.gpu2d.Path} path to apply the fill to.
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.Color.prototype.apply_ = function(path) {
|
| + this.applyToMaterial_(path.interiorMaterial_);
|
| + this.applyToMaterial_(path.exteriorMaterial_);
|
| +};
|
| +
|
| +/**
|
| + * Applies this color to the given material
|
| + * @param {!o3d.Material} material to apply the fill to.
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.Color.prototype.applyToMaterial_ = function(material) {
|
| + var paramName = 'color';
|
| + var paramType = 'ParamFloat4';
|
| + var param = material.getParam(paramName);
|
| + if (!param) {
|
| + param = material.createParam(paramName, paramType);
|
| + }
|
| + param.set(this.r_, this.g_, this.b_, this.a_);
|
| +};
|
| +
|
| +/**
|
| + * Creates a solid color fill.
|
| + * @param {!o3d.Pack} pack the Pack in which to create materials.
|
| + * @param {number} red Red component (0.0 - 1.0).
|
| + * @param {number} green Green component (0.0 - 1.0).
|
| + * @param {number} blue Blue component (0.0 - 1.0).
|
| + * @param {number} alpha Alpha component (0.0 - 1.0).
|
| + * @return {!o3djs.gpu2d.Color} The created Color.
|
| + */
|
| +o3djs.gpu2d.createColor = function(pack, red, green, blue, alpha) {
|
| + var result = new o3djs.gpu2d.Color(pack);
|
| + result.set(red, green, blue, alpha);
|
| + return result;
|
| +};
|
| +
|
| +//----------------------------------------------------------------------
|
| +// Shaders and effects
|
| +
|
| +// TODO(kbr): antialiasing is not supported yet because the ddx
|
| +// and ddy instructions are not part of the shader model 2.0. On
|
| +// Windows we could easily upgrade to ps2.0a, but on Mac and Linux
|
| +// there isn't an easy upgrade path from ARBVP1.0 and ARBFP1.0 which
|
| +// incorporates these instructions.
|
| +//
|
| +// The solution within O3D is to compute the gradients using the
|
| +// closed-form solution in Loop and Blinn's SIGGRAPH '05 paper. This
|
| +// requires computation of the Psi matrix per vertex. In GLSL this is
|
| +// not necessary; derivative instructions are always available there.
|
| +
|
| +/**
|
| + * Generates the source for the shader used on the exterior triangles
|
| + * of the shape -- the ones that evaluate the curve function.
|
| + * @param {boolean} antialias whether to enable antialiasing.
|
| + * @param {string} fillUniforms the uniforms for the fill.
|
| + * @param {string} fillSource the source code snippet for the fill.
|
| + * @return {string}
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.generateLoopBlinnShaderSource_ = function(antialias,
|
| + fillUniforms,
|
| + fillSource) {
|
| + var result = '' +
|
| + 'uniform float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
|
| + fillUniforms +
|
| + '\n' +
|
| + 'struct VertexShaderInput {\n' +
|
| + ' float2 position : POSITION;\n' +
|
| + ' float3 klm : TEXCOORD0;\n' +
|
| + '};\n' +
|
| + '\n' +
|
| + 'struct PixelShaderInput {\n' +
|
| + ' float4 position : POSITION;\n' +
|
| + ' float3 klm : TEXCOORD0;\n' +
|
| + '};\n' +
|
| + '\n' +
|
| + 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
|
| + ' PixelShaderInput output;\n' +
|
| + '\n' +
|
| + ' output.position = mul(float4(input.position, 0, 1),\n' +
|
| + ' worldViewProjection);\n' +
|
| + ' output.klm = input.klm;\n' +
|
| + ' return output;\n' +
|
| + '}\n' +
|
| + '\n' +
|
| + 'float4 pixelShaderFunction(PixelShaderInput input) : COLOR {\n' +
|
| + ' float3 klm = input.klm;\n';
|
| + var alphaComputation;
|
| + if (antialias) {
|
| + alphaComputation = '' +
|
| + ' // Gradients\n' +
|
| + ' float3 px = ddx(input.klm);\n' +
|
| + ' float3 py = ddy(input.klm);\n' +
|
| + '\n' +
|
| + ' // Chain rule\n' +
|
| + ' float k2 = klm.x * klm.x;\n' +
|
| + ' float c = k2 * klm.x - klm.y * klm.z;\n' +
|
| + ' float k23 = 3.0 * k2;\n' +
|
| + ' float cx = k23 * px.x - klm.z * px.y - klm.y * px.z;\n' +
|
| + ' float cy = k23 * py.x - klm.z * py.y - klm.y * py.z;\n' +
|
| + '\n' +
|
| + ' // Signed distance\n' +
|
| + ' float sd = c / sqrt(cx * cx + cy * cy);\n' +
|
| + '\n' +
|
| + ' // Linear alpha\n' +
|
| + ' float alpha = clamp(0.5 - sd, 0.0, 1.0);\n';
|
| + } else {
|
| + alphaComputation = '' +
|
| + ' float t = klm.x * klm.x * klm.x - klm.y * klm.z;\n' +
|
| + ' float alpha = clamp(sign(t), 0.0, 1.0);\n';
|
| + }
|
| +
|
| + return result + alphaComputation +
|
| + '\n' +
|
| + fillSource +
|
| + '}\n' +
|
| + '\n' +
|
| + '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
|
| + '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
|
| + '// #o3d MatrixLoadOrder RowMajor\n';
|
| +};
|
| +
|
| +/**
|
| + * Generates the source for the shader used on the interior triangles
|
| + * of the shape.
|
| + * @param {string} fillUniforms the uniforms for the fill.
|
| + * @param {string} fillSource the source code snippet for the fill.
|
| + * @return {string}
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.generateSolidShaderSource_ = function(fillUniforms, fillSource) {
|
| + var result = '' +
|
| + 'uniform float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
|
| + fillUniforms +
|
| + '\n' +
|
| + 'struct VertexShaderInput {\n' +
|
| + ' float2 position : POSITION;\n' +
|
| + '};\n' +
|
| + '\n' +
|
| + 'struct PixelShaderInput {\n' +
|
| + ' float4 position : POSITION;\n' +
|
| + '};\n' +
|
| + '\n' +
|
| + 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
|
| + ' PixelShaderInput output;\n' +
|
| + '\n' +
|
| + ' output.position = mul(float4(input.position, 0, 1),\n' +
|
| + ' worldViewProjection);\n' +
|
| + ' return output;\n' +
|
| + '}\n' +
|
| + '\n' +
|
| + 'float4 pixelShaderFunction(PixelShaderInput input) : COLOR {\n' +
|
| + ' float alpha = 1.0;\n' +
|
| + fillSource +
|
| + '}\n' +
|
| + '\n' +
|
| + '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
|
| + '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
|
| + '// #o3d MatrixLoadOrder RowMajor\n';
|
| + return result;
|
| +};
|
| +
|
| +/**
|
| + * Enum for the types of fills.
|
| + * @enum
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.FillTypes_ = {
|
| + COLOR: 0
|
| +};
|
| +
|
| +/**
|
| + * Shader code for the various fills, indexed by FillTypes_.
|
| + * @type {!Array.<{uniforms: string, source: string}>}
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.FILL_CODE_ = [
|
| + { uniforms:
|
| + 'uniform float4 color;\n',
|
| + source:
|
| + 'return float4(color.r, color.g, color.b, color.a * alpha);\n'
|
| + }
|
| +];
|
| +
|
| +/**
|
| + * Cache of effects indexed by pack's client ID. Each entry is an
|
| + * array indexed by fill type.
|
| + * @type {!Array.<!Array.<!o3d.Effect>>}
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.interiorEffectCache_ = [];
|
| +
|
| +/**
|
| + * Cache of effects indexed by pack's client ID. Each entry is an
|
| + * array indexed by fill type.
|
| + * @type {!Array.<!Array.<!o3d.Effect>>}
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.exteriorEffectCache_ = [];
|
| +
|
| +/**
|
| + * Loads a fill effect for a Path.
|
| + * @param {!o3d.Pack} pack the Pack in which to create materials.
|
| + * @param {o3djs.gpu2d.FillTypes_} fillType the fill type to create.
|
| + * @param {boolean} interior whether this effect is filling the solid
|
| + * interior portion of the shape or the exterior region containing
|
| + * the curves.
|
| + * @return {!o3d.Effect}
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.loadEffect_ = function(pack, fillType, interior) {
|
| + var effectCache;
|
| + if (interior) {
|
| + effectCache = o3djs.gpu2d.interiorEffectCache_;
|
| + } else {
|
| + effectCache = o3djs.gpu2d.exteriorEffectCache_;
|
| + }
|
| + var effectList = o3djs.gpu2d.getEffectList_(pack, effectCache);
|
| + var effect = effectList[fillType];
|
| + if (!effect) {
|
| + effect = pack.createObject('Effect');
|
| + var result = false;
|
| + var sourceSnippets = o3djs.gpu2d.FILL_CODE_[fillType];
|
| + if (interior) {
|
| + result = effect.loadFromFXString(
|
| + o3djs.gpu2d.generateSolidShaderSource_(sourceSnippets.uniforms,
|
| + sourceSnippets.source));
|
| + } else {
|
| + result = effect.loadFromFXString(
|
| + o3djs.gpu2d.generateLoopBlinnShaderSource_(false,
|
| + sourceSnippets.uniforms,
|
| + sourceSnippets.source));
|
| + }
|
| + if (!result) {
|
| + alert('Error loading shader: interior = ' + interior);
|
| + }
|
| + effectList[fillType] = effect;
|
| + }
|
| + return effect;
|
| +};
|
| +
|
| +/**
|
| + * Fetches and/or creates the effect list for a given pack from the
|
| + * passed effect cache.
|
| + * @param {!o3d.Pack} pack the Pack in which to create materials.
|
| + * @param {!Array.<!Array.<!o3d.Effect>>} effectCache the effect cache.
|
| + * @return {!Array.<o3d.Effect>}
|
| + * @private
|
| + */
|
| +o3djs.gpu2d.getEffectList_ = function(pack, effectCache) {
|
| + var list = effectCache[pack.clientId];
|
| + if (!list) {
|
| + list = [];
|
| + effectCache[pack.clientId] = list;
|
| + }
|
| + return list;
|
| +};
|
| +
|
|
|
| Property changes on: samples/o3djs/gpu2d.js
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|