diff --git a/rsrc/media/jme/skin.vert b/rsrc/media/jme/skin.vert index 736d3ef4..dadf7957 100644 --- a/rsrc/media/jme/skin.vert +++ b/rsrc/media/jme/skin.vert @@ -19,8 +19,6 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#version 110 - #if BONES_PER_VERTEX == 4 #define ATTRIB_TYPE vec4 #elif BONES_PER_VERTEX == 3 diff --git a/src/java/com/threerings/jme/util/JmeUtil.java b/src/java/com/threerings/jme/util/JmeUtil.java index 70f8cf97..52881527 100644 --- a/src/java/com/threerings/jme/util/JmeUtil.java +++ b/src/java/com/threerings/jme/util/JmeUtil.java @@ -21,22 +21,10 @@ package com.threerings.jme.util; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -import java.nio.IntBuffer; - -import org.lwjgl.opengl.ARBShaderObjects; - import com.jme.math.Matrix4f; import com.jme.math.Quaternion; import com.jme.math.Vector3f; import com.jme.scene.Controller; -import com.jme.scene.state.GLSLShaderObjectsState; -import com.jme.system.DisplaySystem; -import com.jme.util.geom.BufferUtils; import com.samskivert.util.StringUtil; @@ -195,49 +183,4 @@ public class JmeUtil } return defaultType; } - - /** - * Loads the specified shaders (prepending the supplied preprocessor definitions) - * and returns a GLSL shader state. One of the supplied streams may be null - * in order to use the fixed-function pipeline for that part. The method returns - * null if the shaders fail to compile (JME will log an error). - * - * @param defs a number of preprocessor definitions to be #defined in both shaders - * (e.g., "ENABLE_FOG", "NUM_LIGHTS 2"). - */ - public static GLSLShaderObjectsState loadShaders ( - InputStream vert, InputStream frag, String... defs) - throws IOException - { - GLSLShaderObjectsState sstate = - DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState(); - sstate.load( - (vert == null) ? null : readSource(vert, defs), - (frag == null) ? null : readSource(frag, defs)); - - // check its link status - IntBuffer linked = BufferUtils.createIntBuffer(1); - ARBShaderObjects.glGetObjectParameterARB(sstate.getProgramID(), - ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB, linked); - return (linked.get() == 0) ? null : sstate; - } - - /** - * Loads an entire source file as a string, prepending the supplied preprocessor definitions. - */ - protected static String readSource (InputStream in, String[] defs) - throws IOException - { - StringBuffer buf = new StringBuffer(); - String ln = System.getProperty("line.separator"); - for (String def : defs) { - buf.append("#define ").append(def).append(ln); - } - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - String line; - while ((line = reader.readLine()) != null) { - buf.append(line).append(ln); - } - return buf.toString(); - } } diff --git a/src/java/com/threerings/jme/util/ShaderCache.java b/src/java/com/threerings/jme/util/ShaderCache.java index dd361cf5..1e1c8641 100644 --- a/src/java/com/threerings/jme/util/ShaderCache.java +++ b/src/java/com/threerings/jme/util/ShaderCache.java @@ -21,16 +21,24 @@ package com.threerings.jme.util; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import java.nio.IntBuffer; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import org.lwjgl.opengl.ARBShaderObjects; + import com.jme.scene.state.GLSLShaderObjectsState; import com.jme.system.DisplaySystem; import com.jme.util.ShaderAttribute; import com.jme.util.ShaderUniform; +import com.jme.util.geom.BufferUtils; import com.samskivert.util.ArrayUtil; import com.samskivert.util.ObjectUtil; @@ -97,16 +105,7 @@ public class ShaderCache if (ddefs != null) { defs = ArrayUtil.concatenate(defs, ddefs); } - GLSLShaderObjectsState pstate; - try { - pstate = JmeUtil.loadShaders( - (vert == null) ? null : _rsrcmgr.getResource(vert), - (frag == null) ? null : _rsrcmgr.getResource(frag), defs); - } catch (IOException e) { - log.warning("Failed to load shaders [vert=" + vert + ", frag=" + frag + - ", error=" + e + "]."); - return false; - } + GLSLShaderObjectsState pstate = loadShaders(vert, frag, defs); if (pstate == null) { return false; } @@ -135,6 +134,67 @@ public class ShaderCache return _programIds.containsKey(new ShaderKey(vert, frag, defs)); } + /** + * Loads the specified shaders (prepending the supplied preprocessor definitions) + * and returns a GLSL shader state. One of the supplied names may be null + * in order to use the fixed-function pipeline for that part. The method returns + * null if the shaders fail to compile (JME will log an error). + * + * @param defs a number of preprocessor definitions to be #defined in both shaders + * (e.g., "ENABLE_FOG", "NUM_LIGHTS 2"). + */ + protected GLSLShaderObjectsState loadShaders (String vert, String frag, String[] defs) + { + GLSLShaderObjectsState sstate = + DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState(); + sstate.load( + (vert == null) ? null : getSource(vert, defs), + (frag == null) ? null : getSource(frag, defs)); + + // check its link status + IntBuffer linked = BufferUtils.createIntBuffer(1); + ARBShaderObjects.glGetObjectParameterARB(sstate.getProgramID(), + ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB, linked); + return (linked.get() == 0) ? null : sstate; + } + + /** + * Retrieves the source code to a shader as a single {@link String}, either by fetching it from + * the cache or loading it from the resource manager (and caching it). Returns + * null (after logging a warning) if the shader couldn't be found. + * + * @param defs an array of definitions to prepend to the result. + */ + protected String getSource (String shader, String[] defs) + { + // fetch the shader source + String source = _sources.get(shader); + if (source == null) { + StringBuffer buf = new StringBuffer(); + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(_rsrcmgr.getResource(shader))); + String line; + while ((line = reader.readLine()) != null) { + buf.append(line).append('\n'); + } + } catch (IOException e) { + log.warning("Failed to load shader [name=" + shader + ", error=" + e + "]."); + return null; + } + _sources.put(shader, (source = buf.toString())); + } + + // prepend the definitions (the version directive comes before anything else) + StringBuffer buf = new StringBuffer(); + buf.append("#version 110\n"); + for (String def : defs) { + buf.append("#define ").append(def).append('\n'); + } + buf.append(source); + return buf.toString(); + } + /** Identifies a cached shader. */ protected static class ShaderKey { @@ -179,6 +239,9 @@ public class ShaderCache /** Provides access to shader source. */ protected ResourceManager _rsrcmgr; + /** Maps shader names to source strings. */ + protected HashMap _sources = new HashMap(); + /** Maps shader keys to linked program ids. */ protected HashMap _programIds = new HashMap(); }