浏览代码

* Add convenience methods clearUniformsSetByCurrentFlag() and resetUniformsNotSetByCurrent() to Shader (normally this is performed by Material)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10772 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Sha..om 12 年之前
父节点
当前提交
55ab8f5d30
共有 1 个文件被更改,包括 366 次插入334 次删除
  1. 366 334
      engine/src/core/com/jme3/shader/Shader.java

+ 366 - 334
engine/src/core/com/jme3/shader/Shader.java

@@ -1,334 +1,366 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * 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 'jMonkeyEngine' 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.
- */
-package com.jme3.shader;
-
-import com.jme3.renderer.Renderer;
-import com.jme3.scene.VertexBuffer;
-import com.jme3.util.IntMap;
-import com.jme3.util.IntMap.Entry;
-import com.jme3.util.ListMap;
-import com.jme3.util.NativeObject;
-import java.util.ArrayList;
-import java.util.Collection;
-
-public final class Shader extends NativeObject {
-    
-    /**
-     * A list of all shader sources currently attached.
-     */
-    private ArrayList<ShaderSource> shaderSourceList;
-
-    /**
-     * Maps uniform name to the uniform variable.
-     */
-    private ListMap<String, Uniform> uniforms;
-
-    /**
-     * Maps attribute name to the location of the attribute in the shader.
-     */
-    private IntMap<Attribute> attribs;
-
-    /**
-     * Type of shader. The shader will control the pipeline of it's type.
-     */
-    public static enum ShaderType {
-        /**
-         * Control fragment rasterization. (e.g color of pixel).
-         */
-        Fragment,
-
-        /**
-         * Control vertex processing. (e.g transform of model to clip space)
-         */
-        Vertex,
-
-        /**
-         * Control geometry assembly. (e.g compile a triangle list from input data)
-         */
-        Geometry;
-    }
-
-    /**
-     * Shader source describes a shader object in OpenGL. Each shader source
-     * is assigned a certain pipeline which it controls (described by it's type).
-     */
-    public static class ShaderSource extends NativeObject {
-
-        ShaderType sourceType;
-        String language;
-        String name;
-        String source;
-        String defines;
-
-        public ShaderSource(ShaderType type){
-            super();
-            this.sourceType = type;
-            if (type == null) {
-                throw new IllegalArgumentException("The shader type must be specified");
-            }
-        }
-        
-        protected ShaderSource(ShaderSource ss){
-            super(ss.id);
-            // No data needs to be copied.
-            // (This is a destructable clone)
-        }
-
-        public ShaderSource(){
-            super();
-        }
-
-        public void setName(String name){
-            this.name = name;
-        }
-
-        public String getName(){
-            return name;
-        }
-
-        public ShaderType getType() {
-            return sourceType;
-        }
-
-        public String getLanguage() {
-            return language;
-        }
-
-        public void setLanguage(String language) {
-            if (language == null) {
-                throw new IllegalArgumentException("Shader language cannot be null");
-            }
-            this.language = language;
-            setUpdateNeeded();
-        }
-
-        public void setSource(String source){
-            if (source == null) {
-                throw new IllegalArgumentException("Shader source cannot be null");
-            }
-            this.source = source;
-            setUpdateNeeded();
-        }
-
-        public void setDefines(String defines){
-            if (defines == null) {
-                throw new IllegalArgumentException("Shader defines cannot be null");
-            }
-            this.defines = defines;
-            setUpdateNeeded();
-        }
-
-        public String getSource(){
-            return source;
-        }
-
-        public String getDefines(){
-            return defines;
-        }
-        
-        @Override
-        public long getUniqueId() {
-            return ((long)OBJTYPE_SHADERSOURCE << 32) | ((long)id);
-        }
-        
-        @Override
-        public String toString(){
-            String nameTxt = "";
-            if (name != null)
-                nameTxt = "name="+name+", ";
-            if (defines != null)
-                nameTxt += "defines, ";
-            
-
-            return getClass().getSimpleName() + "["+nameTxt+"type="
-                                              + sourceType.name()+", language=" + language + "]";
-        }
-
-        public void resetObject(){
-            id = -1;
-            setUpdateNeeded();
-        }
-
-        public void deleteObject(Object rendererObject){
-            ((Renderer)rendererObject).deleteShaderSource(ShaderSource.this);
-        }
-
-        public NativeObject createDestructableClone(){
-            return new ShaderSource(ShaderSource.this);
-        }
-    }
-
-    /**
-     * Initializes the shader for use, must be called after the 
-     * constructor without arguments is used.
-     */
-    public void initialize() {
-        shaderSourceList = new ArrayList<ShaderSource>();
-        uniforms = new ListMap<String, Uniform>();
-        attribs = new IntMap<Attribute>();
-    }
-    
-    /**
-     * Creates a new shader, {@link #initialize() } must be called
-     * after this constructor for the shader to be usable.
-     */
-    public Shader(){
-        super();
-    }
-
-    /**
-     * Do not use this constructor. Used for destructable clones only.
-     */
-    protected Shader(Shader s){
-        super(s.id);
-        
-        // Shader sources cannot be shared, therefore they must
-        // be destroyed together with the parent shader.
-        shaderSourceList = new ArrayList<ShaderSource>();
-        for (ShaderSource source : s.shaderSourceList){
-            shaderSourceList.add( (ShaderSource)source.createDestructableClone() );
-        }
-    }
-
-    /**
-     * Adds source code to a certain pipeline.
-     *
-     * @param type The pipeline to control
-     * @param source The shader source code (in GLSL).
-     * @param defines Preprocessor defines (placed at the beginning of the shader)
-     * @param language The shader source language, currently accepted is GLSL###
-     * where ### is the version, e.g. GLSL100 = GLSL 1.0, GLSL330 = GLSL 3.3, etc.
-     */
-    public void addSource(ShaderType type, String name, String source, String defines, String language){
-        ShaderSource shaderSource = new ShaderSource(type);
-        shaderSource.setSource(source);
-        shaderSource.setName(name);
-        shaderSource.setLanguage(language);
-        if (defines != null) {
-            shaderSource.setDefines(defines);
-        }
-        shaderSourceList.add(shaderSource);
-        setUpdateNeeded();
-    }
-
-    public Uniform getUniform(String name){
-        Uniform uniform = uniforms.get(name);
-        if (uniform == null){
-            uniform = new Uniform();
-            uniform.name = name;
-            uniforms.put(name, uniform);
-        }
-        return uniform;
-    }
-
-    public void removeUniform(String name){
-        uniforms.remove(name);
-    }
-
-    public Attribute getAttribute(VertexBuffer.Type attribType){
-        int ordinal = attribType.ordinal();
-        Attribute attrib = attribs.get(ordinal);
-        if (attrib == null){
-            attrib = new Attribute();
-            attrib.name = attribType.name();
-            attribs.put(ordinal, attrib);
-        }
-        return attrib;
-    }
-
-    public ListMap<String, Uniform> getUniformMap(){
-        return uniforms;
-    }
-
-    public Collection<ShaderSource> getSources(){
-        return shaderSourceList;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + 
-                "[numSources=" + shaderSourceList.size() +
-                ", numUniforms=" + uniforms.size() +
-                ", shaderSources=" + getSources() + "]";
-    }
-
-    /**
-     * Usually called when the shader itself changes or during any
-     * time when the variable locations need to be refreshed.
-     */
-    public void resetLocations() {
-        if (uniforms != null) {
-            // NOTE: Shader sources will be reset seperately from the shader itself.
-            for (Uniform uniform : uniforms.values()) {
-                uniform.reset(); // fixes issue with re-initialization
-            }
-        }
-        if (attribs != null) {
-            for (Entry<Attribute> entry : attribs) {
-                entry.getValue().location = ShaderVariable.LOC_UNKNOWN;
-            }
-        }
-    }
-
-    @Override
-    public void setUpdateNeeded(){
-        super.setUpdateNeeded();
-        resetLocations();
-    }
-
-    /**
-     * Called by the object manager to reset all object IDs. This causes
-     * the shader to be reuploaded to the GPU incase the display was restarted.
-     */
-    @Override
-    public void resetObject() {
-        this.id = -1;
-        for (ShaderSource source : shaderSourceList){
-            source.resetObject();
-        }
-        setUpdateNeeded();
-    }
-
-    @Override
-    public void deleteObject(Object rendererObject) {
-        ((Renderer)rendererObject).deleteShader(this);
-    }
-
-    public NativeObject createDestructableClone(){
-        return new Shader(this);
-    }
-
-    @Override
-    public long getUniqueId() {
-        return ((long)OBJTYPE_SHADER << 32) | ((long)id);
-    }
-}
+/*
+ * Copyright (c) 2009-2012 jMonkeyEngine
+ * 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 'jMonkeyEngine' 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.
+ */
+package com.jme3.shader;
+
+import com.jme3.renderer.Renderer;
+import com.jme3.scene.VertexBuffer;
+import com.jme3.util.IntMap;
+import com.jme3.util.IntMap.Entry;
+import com.jme3.util.ListMap;
+import com.jme3.util.NativeObject;
+import java.util.ArrayList;
+import java.util.Collection;
+
+public final class Shader extends NativeObject {
+    
+    /**
+     * A list of all shader sources currently attached.
+     */
+    private ArrayList<ShaderSource> shaderSourceList;
+
+    /**
+     * Maps uniform name to the uniform variable.
+     */
+    private ListMap<String, Uniform> uniforms;
+
+    /**
+     * Maps attribute name to the location of the attribute in the shader.
+     */
+    private IntMap<Attribute> attribs;
+
+    /**
+     * Type of shader. The shader will control the pipeline of it's type.
+     */
+    public static enum ShaderType {
+        /**
+         * Control fragment rasterization. (e.g color of pixel).
+         */
+        Fragment,
+
+        /**
+         * Control vertex processing. (e.g transform of model to clip space)
+         */
+        Vertex,
+
+        /**
+         * Control geometry assembly. (e.g compile a triangle list from input data)
+         */
+        Geometry;
+    }
+
+    /**
+     * Shader source describes a shader object in OpenGL. Each shader source
+     * is assigned a certain pipeline which it controls (described by it's type).
+     */
+    public static class ShaderSource extends NativeObject {
+
+        ShaderType sourceType;
+        String language;
+        String name;
+        String source;
+        String defines;
+
+        public ShaderSource(ShaderType type){
+            super();
+            this.sourceType = type;
+            if (type == null) {
+                throw new IllegalArgumentException("The shader type must be specified");
+            }
+        }
+        
+        protected ShaderSource(ShaderSource ss){
+            super(ss.id);
+            // No data needs to be copied.
+            // (This is a destructable clone)
+        }
+
+        public ShaderSource(){
+            super();
+        }
+
+        public void setName(String name){
+            this.name = name;
+        }
+
+        public String getName(){
+            return name;
+        }
+
+        public ShaderType getType() {
+            return sourceType;
+        }
+
+        public String getLanguage() {
+            return language;
+        }
+
+        public void setLanguage(String language) {
+            if (language == null) {
+                throw new IllegalArgumentException("Shader language cannot be null");
+            }
+            this.language = language;
+            setUpdateNeeded();
+        }
+
+        public void setSource(String source){
+            if (source == null) {
+                throw new IllegalArgumentException("Shader source cannot be null");
+            }
+            this.source = source;
+            setUpdateNeeded();
+        }
+
+        public void setDefines(String defines){
+            if (defines == null) {
+                throw new IllegalArgumentException("Shader defines cannot be null");
+            }
+            this.defines = defines;
+            setUpdateNeeded();
+        }
+
+        public String getSource(){
+            return source;
+        }
+
+        public String getDefines(){
+            return defines;
+        }
+        
+        @Override
+        public long getUniqueId() {
+            return ((long)OBJTYPE_SHADERSOURCE << 32) | ((long)id);
+        }
+        
+        @Override
+        public String toString(){
+            String nameTxt = "";
+            if (name != null)
+                nameTxt = "name="+name+", ";
+            if (defines != null)
+                nameTxt += "defines, ";
+            
+
+            return getClass().getSimpleName() + "["+nameTxt+"type="
+                                              + sourceType.name()+", language=" + language + "]";
+        }
+
+        public void resetObject(){
+            id = -1;
+            setUpdateNeeded();
+        }
+
+        public void deleteObject(Object rendererObject){
+            ((Renderer)rendererObject).deleteShaderSource(ShaderSource.this);
+        }
+
+        public NativeObject createDestructableClone(){
+            return new ShaderSource(ShaderSource.this);
+        }
+    }
+
+    /**
+     * Initializes the shader for use, must be called after the 
+     * constructor without arguments is used.
+     */
+    public void initialize() {
+        shaderSourceList = new ArrayList<ShaderSource>();
+        uniforms = new ListMap<String, Uniform>();
+        attribs = new IntMap<Attribute>();
+    }
+    
+    /**
+     * Creates a new shader, {@link #initialize() } must be called
+     * after this constructor for the shader to be usable.
+     */
+    public Shader(){
+        super();
+    }
+
+    /**
+     * Do not use this constructor. Used for destructable clones only.
+     */
+    protected Shader(Shader s){
+        super(s.id);
+        
+        // Shader sources cannot be shared, therefore they must
+        // be destroyed together with the parent shader.
+        shaderSourceList = new ArrayList<ShaderSource>();
+        for (ShaderSource source : s.shaderSourceList){
+            shaderSourceList.add( (ShaderSource)source.createDestructableClone() );
+        }
+    }
+
+    /**
+     * Adds source code to a certain pipeline.
+     *
+     * @param type The pipeline to control
+     * @param source The shader source code (in GLSL).
+     * @param defines Preprocessor defines (placed at the beginning of the shader)
+     * @param language The shader source language, currently accepted is GLSL###
+     * where ### is the version, e.g. GLSL100 = GLSL 1.0, GLSL330 = GLSL 3.3, etc.
+     */
+    public void addSource(ShaderType type, String name, String source, String defines, String language){
+        ShaderSource shaderSource = new ShaderSource(type);
+        shaderSource.setSource(source);
+        shaderSource.setName(name);
+        shaderSource.setLanguage(language);
+        if (defines != null) {
+            shaderSource.setDefines(defines);
+        }
+        shaderSourceList.add(shaderSource);
+        setUpdateNeeded();
+    }
+
+    public Uniform getUniform(String name){
+        Uniform uniform = uniforms.get(name);
+        if (uniform == null){
+            uniform = new Uniform();
+            uniform.name = name;
+            uniforms.put(name, uniform);
+        }
+        return uniform;
+    }
+
+    public void removeUniform(String name){
+        uniforms.remove(name);
+    }
+
+    public Attribute getAttribute(VertexBuffer.Type attribType){
+        int ordinal = attribType.ordinal();
+        Attribute attrib = attribs.get(ordinal);
+        if (attrib == null){
+            attrib = new Attribute();
+            attrib.name = attribType.name();
+            attribs.put(ordinal, attrib);
+        }
+        return attrib;
+    }
+
+    public ListMap<String, Uniform> getUniformMap(){
+        return uniforms;
+    }
+
+    public Collection<ShaderSource> getSources(){
+        return shaderSourceList;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + 
+                "[numSources=" + shaderSourceList.size() +
+                ", numUniforms=" + uniforms.size() +
+                ", shaderSources=" + getSources() + "]";
+    }
+
+    /**
+     * Removes the "set-by-current-material" flag from all uniforms.
+     * When a uniform is modified after this call, the flag shall
+     * become "set-by-current-material". 
+     * A call to {@link #resetUniformsNotSetByCurrent() } will reset
+     * all uniforms that do not have the "set-by-current-material" flag
+     * to their default value (usually all zeroes or false).
+     */
+    public void clearUniformsSetByCurrentFlag() {
+        int size = uniforms.size();
+        for (int i = 0; i < size; i++) {
+            Uniform u = uniforms.getValue(i);
+            u.clearSetByCurrentMaterial();
+        }
+    }
+
+    /**
+     * Resets all uniforms that do not have the "set-by-current-material" flag
+     * to their default value (usually all zeroes or false).
+     * When a uniform is modified, that flag is set, to remove the flag,
+     * use {@link #clearUniformsSetByCurrent() }.
+     */
+    public void resetUniformsNotSetByCurrent() {
+        int size = uniforms.size();
+        for (int i = 0; i < size; i++) {
+            Uniform u = uniforms.getValue(i);
+            if (!u.isSetByCurrentMaterial()) {
+                u.clearValue();
+            }
+        }
+    }
+
+    /**
+     * Usually called when the shader itself changes or during any
+     * time when the variable locations need to be refreshed.
+     */
+    public void resetLocations() {
+        if (uniforms != null) {
+            // NOTE: Shader sources will be reset seperately from the shader itself.
+            for (Uniform uniform : uniforms.values()) {
+                uniform.reset(); // fixes issue with re-initialization
+            }
+        }
+        if (attribs != null) {
+            for (Entry<Attribute> entry : attribs) {
+                entry.getValue().location = ShaderVariable.LOC_UNKNOWN;
+            }
+        }
+    }
+
+    @Override
+    public void setUpdateNeeded(){
+        super.setUpdateNeeded();
+        resetLocations();
+    }
+
+    /**
+     * Called by the object manager to reset all object IDs. This causes
+     * the shader to be reuploaded to the GPU incase the display was restarted.
+     */
+    @Override
+    public void resetObject() {
+        this.id = -1;
+        for (ShaderSource source : shaderSourceList){
+            source.resetObject();
+        }
+        setUpdateNeeded();
+    }
+
+    @Override
+    public void deleteObject(Object rendererObject) {
+        ((Renderer)rendererObject).deleteShader(this);
+    }
+
+    public NativeObject createDestructableClone(){
+        return new Shader(this);
+    }
+
+    @Override
+    public long getUniqueId() {
+        return ((long)OBJTYPE_SHADER << 32) | ((long)id);
+    }
+}