From c755fd626a5ecf19759f66df9324771b240bd793 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 May 2007 00:55:19 +0000 Subject: [PATCH] To reduce shader state changes and compilations, just use the four-bone-per-vertex configuration for all skinned meshes. Depending on the models we have, it may be worth compiling a separate one for two bones per vertex. Added a hook to customize the material color (for per-vertex colors, e.g.) git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@245 ed5b42cb-e716-0410-a449-f6a68f950b19 --- rsrc/media/jme/skin.vert | 32 ++++++------------- .../com/threerings/jme/model/SkinMesh.java | 25 +++++---------- .../com/threerings/jme/util/ShaderConfig.java | 23 +++++++++---- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/rsrc/media/jme/skin.vert b/rsrc/media/jme/skin.vert index 5bdc1393..e74c66cf 100644 --- a/rsrc/media/jme/skin.vert +++ b/rsrc/media/jme/skin.vert @@ -19,24 +19,14 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#if BONES_PER_VERTEX == 4 - #define ATTRIB_TYPE vec4 -#elif BONES_PER_VERTEX == 3 - #define ATTRIB_TYPE vec3 -#elif BONES_PER_VERTEX == 2 - #define ATTRIB_TYPE vec2 -#else - #define ATTRIB_TYPE float -#endif - /** The bone transforms. */ uniform mat4 boneTransforms[MAX_BONE_COUNT]; /** The bone indices. */ -attribute ATTRIB_TYPE boneIndices; +attribute vec4 boneIndices; /** The bone weights. */ -attribute ATTRIB_TYPE boneWeights; +attribute vec4 boneWeights; /** The amount of fog. */ #ifdef FOG @@ -51,17 +41,13 @@ void main () vec4 normal4 = vec4(gl_Normal, 0.0); // add up the vertex as transformed by each bone and scaled by each weight - #if BONES_PER_VERTEX == 1 - vec4 modelVertex = boneTransforms[int(boneIndices)] * gl_Vertex * boneWeights; - vec4 modelNormal = boneTransforms[int(boneIndices)] * normal4 * boneWeights; - #else - vec4 modelVertex = boneTransforms[int(boneIndices[0])] * gl_Vertex * boneWeights[0]; - vec4 modelNormal = boneTransforms[int(boneIndices[0])] * normal4 * boneWeights[0]; - for (int ii = 1; ii < BONES_PER_VERTEX; ii++) { - modelVertex += boneTransforms[int(boneIndices[ii])] * gl_Vertex * boneWeights[ii]; - modelNormal += boneTransforms[int(boneIndices[ii])] * normal4 * boneWeights[ii]; - } - #endif + vec4 modelVertex = vec4(0.0, 0.0, 0.0, 0.0); + vec4 modelNormal = vec4(0.0, 0.0, 0.0, 0.0); + for (int ii = 0; ii < 4; ii++) { + mat4 boneTransform = boneTransforms[int(boneIndices[ii])]; + modelVertex += boneTransform * gl_Vertex * boneWeights[ii]; + modelNormal += boneTransform * normal4 * boneWeights[ii]; + } // apply the standard transformation gl_Position = gl_ModelViewProjectionMatrix * modelVertex; diff --git a/src/java/com/threerings/jme/model/SkinMesh.java b/src/java/com/threerings/jme/model/SkinMesh.java index 3610d133..4aaa6990 100644 --- a/src/java/com/threerings/jme/model/SkinMesh.java +++ b/src/java/com/threerings/jme/model/SkinMesh.java @@ -408,7 +408,7 @@ public class SkinMesh extends ModelMesh if (bonesPerVertex > MAX_SHADER_BONES_PER_VERTEX) { return; } - _sconfig = new SkinShaderConfig(scache, bonesPerVertex, _emissiveMap != null); + _sconfig = new SkinShaderConfig(scache, _emissiveMap != null); if (_sconfig.update(getBatch(0).states)) { setShaderAttributes(); setRenderState(_sconfig.getState()); @@ -618,20 +618,19 @@ public class SkinMesh extends ModelMesh */ protected void setShaderAttributes () { - int bonesPerVertex = _sconfig.getBonesPerVertex(); - int size = getBatch(0).getVertexCount() * bonesPerVertex; + int size = getBatch(0).getVertexCount() * 4; ByteBuffer bibuf = BufferUtils.createByteBuffer(size); FloatBuffer bwbuf = BufferUtils.createFloatBuffer(size); for (WeightGroup group : _weightGroups) { - byte[] indices = new byte[bonesPerVertex]; - for (int ii = 0; ii < indices.length; ii++) { + byte[] indices = new byte[4]; + for (int ii = 0; ii < 4; ii++) { indices[ii] = (byte)((ii < group.bones.length) ? ListUtil.indexOf(_bones, group.bones[ii]) : 0); } for (int ii = 0, widx = 0; ii < group.vertexCount; ii++) { bibuf.put(indices); - for (int jj = 0; jj < bonesPerVertex; jj++) { + for (int jj = 0; jj < 4; jj++) { bwbuf.put((jj < group.bones.length) ? group.weights[widx++] : 0f); } } @@ -640,17 +639,16 @@ public class SkinMesh extends ModelMesh bwbuf.rewind(); GLSLShaderObjectsState sstate = _sconfig.getState(); - sstate.setAttributePointer("boneIndices", bonesPerVertex, false, false, 0, bibuf); - sstate.setAttributePointer("boneWeights", bonesPerVertex, false, 0, bwbuf); + sstate.setAttributePointer("boneIndices", 4, false, false, 0, bibuf); + sstate.setAttributePointer("boneWeights", 4, false, 0, bwbuf); } /** Tracks the configuration of a skin shader. */ protected static class SkinShaderConfig extends ShaderConfig { - public SkinShaderConfig (ShaderCache scache, int bonesPerVertex, boolean emissiveMapped) + public SkinShaderConfig (ShaderCache scache, boolean emissiveMapped) { super(scache); - _bonesPerVertex = bonesPerVertex; _emissiveMapped = emissiveMapped; // set bindings from texture units to samplers @@ -662,11 +660,6 @@ public class SkinMesh extends ModelMesh } } - public int getBonesPerVertex () - { - return _bonesPerVertex; - } - @Override // documentation inherited protected String getVertexShader () { @@ -683,7 +676,6 @@ public class SkinMesh extends ModelMesh protected void getDefinitions (ArrayList defs) { super.getDefinitions(defs); - defs.add("BONES_PER_VERTEX " + _bonesPerVertex); if (_emissiveMapped) { defs.add("EMISSIVE_MAPPED"); } @@ -696,7 +688,6 @@ public class SkinMesh extends ModelMesh ddefs.add("MAX_BONE_COUNT " + MAX_SHADER_BONE_COUNT); } - protected int _bonesPerVertex; protected boolean _emissiveMapped; } diff --git a/src/java/com/threerings/jme/util/ShaderConfig.java b/src/java/com/threerings/jme/util/ShaderConfig.java index 57792b4c..8aa073a9 100644 --- a/src/java/com/threerings/jme/util/ShaderConfig.java +++ b/src/java/com/threerings/jme/util/ShaderConfig.java @@ -240,12 +240,8 @@ public abstract class ShaderConfig // add snippets for each of the lights for (int ii = 0; ii < _lights.length; ii++) { - LightConfig light = _lights[ii]; - if (light.type == Light.LT_POINT) { - buf.append(POINT_LIGHT_SNIPPET.replace("%", Integer.toString(ii))); - } else if (light.type == Light.LT_DIRECTIONAL) { - buf.append(DIRECTIONAL_LIGHT_SNIPPET.replace("%", Integer.toString(ii))); - } + String snippet = getLightSnippet(_lights[ii].type); + buf.append(snippet.replace("%", Integer.toString(ii))); } // the alpha value comes from the diffuse color in the material @@ -281,6 +277,21 @@ public abstract class ShaderConfig ddefs.add(buf.toString()); } + /** + * Returns a code snippet that adds the influence of a light of the specified type (after + * replacing '%' with the light index). + */ + protected String getLightSnippet (int type) + { + if (type == Light.LT_POINT) { + return POINT_LIGHT_SNIPPET; + } else if (type == Light.LT_DIRECTIONAL) { + return DIRECTIONAL_LIGHT_SNIPPET; + } else { + return ""; + } + } + /** The configuration of a single light in a {@link LightState}. */ protected static class LightConfig implements Cloneable