| Index: o3djs/effect.js
|
| ===================================================================
|
| --- o3djs/effect.js (revision 59332)
|
| +++ o3djs/effect.js (working copy)
|
| @@ -409,10 +409,11 @@
|
| * @param {boolean} specular Whether to include stuff for diffuse
|
| * calculations.
|
| * @param {boolean} bumpSampler Whether there is a bump sampler.
|
| + * @param {boolean} skinning Whether this mesh has a skin.
|
| * @return {string} The code for the declarations.
|
| */
|
| o3djs.effect.buildAttributeDecls =
|
| - function(material, diffuse, specular, bumpSampler) {
|
| + function(material, diffuse, specular, bumpSampler, skinning) {
|
| var str = o3djs.effect.BEGIN_IN_STRUCT +
|
| o3djs.effect.ATTRIBUTE + o3djs.effect.FLOAT4 + ' ' + 'position' +
|
| o3djs.effect.semanticSuffix('POSITION') + ';\n';
|
| @@ -420,6 +421,12 @@
|
| str += o3djs.effect.ATTRIBUTE + o3djs.effect.FLOAT3 + ' ' + 'normal' +
|
| o3djs.effect.semanticSuffix('NORMAL') + ';\n';
|
| }
|
| + if (skinning) {
|
| + str += o3djs.effect.ATTRIBUTE + o3djs.effect.FLOAT4 + ' influenceWeights' +
|
| + o3djs.effect.semanticSuffix('BLENDWEIGHT') + ';\n';
|
| + str += o3djs.effect.ATTRIBUTE + o3djs.effect.FLOAT4 + ' influenceIndices' +
|
| + o3djs.effect.semanticSuffix('BLENDINDICES') + ';\n';
|
| + }
|
| str += o3djs.effect.buildTexCoords(material, false) +
|
| o3djs.effect.buildBumpInputCoords(bumpSampler) +
|
| o3djs.effect.END_STRUCT;
|
| @@ -838,7 +845,22 @@
|
| var p = o3djs.effect;
|
| var bumpSampler = material.getParam('bumpSampler');
|
| var bumpUVInterpolant;
|
| + var skinning;
|
|
|
| + var maxSkinInfluences = 4;
|
| +
|
| + // Hardcode reasonable maximum for number of skinning uniforms.
|
| + // glsl: Table 6.19: minimum MAX_VERTEX_UNIFORM_VECTORS is 128.
|
| + // (DX9 requires a minimum of 256, so not a problem in o3d).
|
| + var maxSkinUniforms = 36 * 3;
|
| + if (o3djs.base.o3d && o3djs.base.o3d.SkinEval &&
|
| + o3djs.base.o3d.SkinEval.getMaxNumBones) {
|
| + maxSkinUniforms = o3d.SkinEval.getMaxNumBones(material) * 3;
|
| + skinning = true;
|
| + } else {
|
| + skinning = false;
|
| + }
|
| +
|
| /**
|
| * Extracts the texture type from a texture param.
|
| * @param {!o3d.ParamTexture} textureParam The texture parameter to
|
| @@ -906,6 +928,17 @@
|
| };
|
|
|
| /**
|
| + * If skinning is enabled, builds the bone matrix uniform variables needed
|
| + * for skinning. Otherwise, returns the empty string.
|
| + * @return {string} The effect code for skinning uniforms.
|
| + */
|
| + var buildSkinningUniforms = function() {
|
| + return skinning ? 'uniform ' + p.FLOAT4 + ' boneToWorld3x4' +
|
| + '[' + maxSkinUniforms + '];\n' +
|
| + 'uniform float usingSkinShader;\n' : '';
|
| + };
|
| +
|
| + /**
|
| * Builds uniform parameters for a given color input. If the material
|
| * has a sampler parameter, a sampler uniform is created, otherwise a
|
| * float4 color value is created.
|
| @@ -967,6 +1000,7 @@
|
| var buildConstantShaderString = function(material, descriptions) {
|
| descriptions.push('constant');
|
| return buildCommonVertexUniforms() +
|
| + buildSkinningUniforms() +
|
| buildVertexDecls(material, false, false) +
|
| p.beginVertexShaderMain() +
|
| positionVertexShaderCode() +
|
| @@ -994,6 +1028,7 @@
|
| descriptions.push('lambert');
|
| return buildCommonVertexUniforms() +
|
| buildLightingUniforms() +
|
| + buildSkinningUniforms() +
|
| buildVertexDecls(material, true, false) +
|
| p.beginVertexShaderMain() +
|
| p.buildUVPassthroughs(material) +
|
| @@ -1041,6 +1076,7 @@
|
| descriptions.push('phong');
|
| return buildCommonVertexUniforms() +
|
| buildLightingUniforms() +
|
| + buildSkinningUniforms() +
|
| buildVertexDecls(material, true, true) +
|
| p.beginVertexShaderMain() +
|
| p.buildUVPassthroughs(material) +
|
| @@ -1099,6 +1135,7 @@
|
| descriptions.push('phong');
|
| return buildCommonVertexUniforms() +
|
| buildLightingUniforms() +
|
| + buildSkinningUniforms() +
|
| buildVertexDecls(material, true, true) +
|
| p.beginVertexShaderMain() +
|
| p.buildUVPassthroughs(material) +
|
| @@ -1149,9 +1186,27 @@
|
| * @return {string} The code for the vertex shader.
|
| */
|
| var positionVertexShaderCode = function() {
|
| - return ' ' + p.VERTEX_VARYING_PREFIX + 'position = ' +
|
| - p.mul(p.ATTRIBUTE_PREFIX +
|
| - 'position', 'worldViewProjection') + ';\n';
|
| + var attribute_position = p.ATTRIBUTE_PREFIX + 'position';
|
| + if (skinning) {
|
| + return ' ' + p.FLOAT4 + ' weightedpos = ' + attribute_position + ';\n' +
|
| + ' for (int i = 0; i < ' + maxSkinInfluences + '; i++) {\n' +
|
| + ' ' + p.FLOAT4 + ' temp = ' + p.FLOAT4 + '(' +
|
| + 'dot(boneToWorld3x4[int(influenceIndices[i] * 3.0)], ' +
|
| + attribute_position + '),\n' +
|
| + ' dot(boneToWorld3x4[int(influenceIndices[i] * 3.0 + 1.0)], ' +
|
| + attribute_position + '),\n' +
|
| + ' dot(boneToWorld3x4[int(influenceIndices[i] * 3.0 + 2.0)], ' +
|
| + attribute_position + '),\n' +
|
| + ' 1.0);\n' +
|
| + ' weightedpos += usingSkinShader * influenceWeights[i] * ' +
|
| + '(temp - ' + attribute_position + ');\n' +
|
| + ' }\n' +
|
| + ' ' + p.VERTEX_VARYING_PREFIX + 'position = ' +
|
| + p.mul('weightedpos', 'worldViewProjection') + ';\n';
|
| + } else {
|
| + return ' ' + p.VERTEX_VARYING_PREFIX + 'position = ' +
|
| + p.mul(attribute_position, 'worldViewProjection') + ';\n';
|
| + }
|
| };
|
|
|
| /**
|
| @@ -1159,10 +1214,29 @@
|
| * @return {string} The code for the vertex shader.
|
| */
|
| var normalVertexShaderCode = function() {
|
| - return ' ' + p.VERTEX_VARYING_PREFIX + 'normal = ' +
|
| - p.mul(p.FLOAT4 + '(' +
|
| - p.ATTRIBUTE_PREFIX +
|
| - 'normal, 0)', 'worldInverseTranspose') + '.xyz;\n';
|
| + var attribute_normal = p.ATTRIBUTE_PREFIX + 'normal';
|
| + if (skinning) {
|
| + return ' ' + p.FLOAT3 + ' weightednorm = ' + attribute_normal + ';\n' +
|
| + ' for (int i = 0; i < ' + maxSkinInfluences + '; i++) {\n' +
|
| + ' ' + p.FLOAT3 + ' temp = ' + p.FLOAT3 + '(' +
|
| + 'dot(boneToWorld3x4[int(influenceIndices[i] * 3.0)].xyz, ' +
|
| + attribute_normal + '),\n' +
|
| + ' dot(boneToWorld3x4[int(influenceIndices[i] * 3.0 + 1.0)].xyz, ' +
|
| + attribute_normal + '),\n' +
|
| + ' dot(boneToWorld3x4[int(influenceIndices[i] * 3.0 + 2.0)].xyz, ' +
|
| + attribute_normal + '));\n' +
|
| + ' weightednorm += usingSkinShader * influenceWeights[i] * ' +
|
| + '(temp - ' + attribute_normal + ');\n' +
|
| + ' }\n' +
|
| + ' ' + p.VERTEX_VARYING_PREFIX + 'normal = ' +
|
| + p.mul(p.FLOAT4 + '(' + 'weightednorm' + ', 0)',
|
| + 'worldInverseTranspose') + '.xyz;\n';
|
| + } else {
|
| + return ' ' + p.VERTEX_VARYING_PREFIX + 'normal = ' +
|
| + p.mul(p.FLOAT4 + '(' +
|
| + attribute_normal + ', 0)', 'worldInverseTranspose') +
|
| + '.xyz;\n';
|
| + }
|
| };
|
|
|
| /**
|
| @@ -1238,7 +1312,7 @@
|
| */
|
| var buildVertexDecls = function(material, diffuse, specular) {
|
| return p.buildAttributeDecls(
|
| - material, diffuse, specular, bumpSampler) +
|
| + material, diffuse, specular, bumpSampler, skinning) +
|
| p.buildVaryingDecls(
|
| material, diffuse, specular, bumpSampler);
|
| };
|
|
|