diff --git a/engine/src/core-data/Common/MatDefs/Misc/UnshadedNodes.j3md b/engine/src/core-data/Common/MatDefs/Misc/UnshadedNodes.j3md
index 8785ed968..f9fb05288 100644
--- a/engine/src/core-data/Common/MatDefs/Misc/UnshadedNodes.j3md
+++ b/engine/src/core-data/Common/MatDefs/Misc/UnshadedNodes.j3md
@@ -6,11 +6,14 @@ MaterialDef UnshadedNodes {
         Color Color (Color)
         Boolean VertexColor (UseVertexColor)
         Boolean SeparateTexCoord
-     
-        //FOG parameters
-        Boolean UseFog
-        Float FogDensity :1
-        Color FogColor : 1 1 1 1
+
+        // Alpha threshold for fragment discarding
+        Float AlphaDiscardThreshold (AlphaTestFallOff)
+
+        // For hardware skinning
+        Int NumberOfBones
+        Matrix4Array BoneMatrices
+   
     }
 
     Technique {
@@ -21,16 +24,20 @@ MaterialDef UnshadedNodes {
             WorldViewMatrix
         }
       
-        VertexShaderNodes{            
-            ShaderNode FogFactor{
-                Definition: FogFactor : Common/MatDefs/ShaderNodes/Fog/Fog.j3sn
-                Condition: UseFog
-                InputMapping{  
-                    modelViewMatrix = WorldParam.WorldViewMatrix
-                    modelPosition = Global.position
-                    fogDensity = MatParam.FogDensity
-                }                
-            }           
+        VertexShaderNodes{    
+            ShaderNode GpuSkinning{
+                Definition: BasicGPUSkinning : Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn
+                Condition : NumberOfBones
+                InputMapping{
+                    modelPosition = Global.position;
+                    boneMatrices = MatParam.BoneMatrices
+                    boneWeight = Attr.inHWBoneWeight
+                    boneIndex = Attr.inHWBoneIndex
+                }
+                OutputMapping{
+                    Global.position = modModelPosition
+                }
+            }
             ShaderNode UnshadedVert{
                 Definition: CommonVert : Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn
                 InputMapping{
@@ -44,8 +51,6 @@ MaterialDef UnshadedNodes {
                     Global.position = projPosition
                 }
             }
-           
-           
         }
         FragmentShaderNodes{
             ShaderNode UnshadedFrag{
@@ -61,6 +66,15 @@ MaterialDef UnshadedNodes {
                     Global.outColor = color
                 }
             }
+
+            ShaderNode AlphaDiscardThreshold{
+                Definition: AlphaDiscard : Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn
+                Condition : AlphaDiscardThreshold
+                InputMapping{
+                    alpha = Global.outColor.a
+                    threshold =  MatParam.AlphaDiscardThreshold                  
+                }                
+            }
             ShaderNode LightMap{
                 Definition: LightMapping : Common/MatDefs/ShaderNodes/LightMapping/LightMapping.j3sn
                 Condition: LightMap
@@ -74,19 +88,7 @@ MaterialDef UnshadedNodes {
                     Global.outColor = color
                 }
             }            
-            
-            ShaderNode FogOutput{
-                Definition: FogOutput : Common/MatDefs/ShaderNodes/Fog/Fog.j3sn
-                Condition: UseFog
-                InputMapping{  
-                    fogFactor = FogFactor.fogFactor
-                    color = Global.outColor
-                    fogColor = MatParam.FogColor
-                }
-                OutputMapping{
-                    Global.outColor = color
-                }
-            }
+                      
         }        
 
     }
diff --git a/engine/src/core-data/Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn b/engine/src/core-data/Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn
new file mode 100644
index 000000000..00b30aa92
--- /dev/null
+++ b/engine/src/core-data/Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn
@@ -0,0 +1,18 @@
+ShaderNodeDefinitions{
+    ShaderNodeDefinition AlphaDiscard {      
+        Type: Fragment
+        Shader GLSL100: Common/MatDefs/ShaderNodes/Basic/alphaDiscard.frag
+        Documentation{
+            Discards the current pixel if its alpha channel value is below the given threshold
+            @input alpha the alpha value 
+            @input threshold the discard threshold          
+        }
+        Input {            
+            float alpha
+            float threshold
+        }
+        Output {
+            None
+        }
+    }
+}
\ No newline at end of file
diff --git a/engine/src/core-data/Common/MatDefs/ShaderNodes/Basic/alphaDiscard.frag b/engine/src/core-data/Common/MatDefs/ShaderNodes/Basic/alphaDiscard.frag
new file mode 100644
index 000000000..7a1c8c701
--- /dev/null
+++ b/engine/src/core-data/Common/MatDefs/ShaderNodes/Basic/alphaDiscard.frag
@@ -0,0 +1,3 @@
+void main(){
+    if( alpha <= threshold )discard;
+}
\ No newline at end of file
diff --git a/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn b/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn
new file mode 100644
index 000000000..2b734b5c8
--- /dev/null
+++ b/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn
@@ -0,0 +1,61 @@
+ShaderNodesDefinitions {            
+    ShaderNodeDefinition BasicGPUSkinning{
+        Type: Vertex
+        Shader GLSL100: Common/MatDefs/ShaderNodes/HardwareSkinning/basicGpuSkinning.vert
+        Documentation {            
+            This Node is responsible for computing vertex positions transformation 
+            of the vertex due to skinning in model space
+            Note that the input position and the output are both in model Space so the output 
+            of this node will need to be translated to projection space.
+            This shader node doesn't take Normals and Tangent into account for full support use FullGPUSkinning
+            IMPORTANT NOTE : for this node to work properly, you must declare a Int NumberOfBones material parameter to which the number of bones will be passed.
+            @input modelPosition the vertex position in model space (usually assigned with Attr.inPosition or Global.position)
+            @input boneMatrices an array of matrice holding the transforms of the bones assigned to this vertex. Its size is defined by the NumberOfBones material parameter
+            @input boneWeight a vec4 holding the bone weights applied to this vertex (4 weights max).
+            @input boneIndex a vec4 holding the bone indices assignes to this vertex (4 bones max).            
+            @output modModelPosition transformed position of the vertex in model space.            
+        }
+        Input{
+            vec4 modelPosition
+            mat4 boneMatrices[NumberOfBones]
+            vec4 boneWeight
+            vec4 boneIndex                    
+        }
+        Output{
+            vec4 modModelPosition                    
+        }
+    } 
+    ShaderNodeDefinition FullGPUSkinning{
+        Type: Vertex
+        Shader GLSL100: Common/MatDefs/ShaderNodes/HardwareSkinning/fullGpuSkinning.vert
+        Documentation {            
+            This Node is responsible for computing vertex positions, normals and tangents transformation 
+            of the vertex due to skinning in model space
+            Note that the input position and the output are both in model Space so the output 
+            of this node will need to be translated to projection space.         
+            IMPORTANT NOTE : for this node to work properly, you must declare a Int NumberOfBones material parameter to which the number of bones will be passed.
+            @input modelPosition the vertex position in model space (usually assigned with Attr.inPosition or Global.position)
+            @input modelNormal the vertex normal in model space (usually assigned with Attr.inNormal)
+            @input modelTangent the vertex tangent in model space (usually assigned with Attr.inTangent)
+            @input boneMatrices an array of matrice holding the transforms of the bones assigned to this vertex. Its size is defined by the NumberOfBones material parameter
+            @input boneWeight a vec4 holding the bone weights applied to this vertex (4 weights max).
+            @input boneIndex a vec4 holding the bone indices assignes to this vertex (4 bones max).            
+            @output modModelPosition transformed position of the vertex in model space. 
+            @output modModelNormal transformed normal of the vertex in model space. 
+            @output modModelTangent transformed tangent of the vertex in model space.            
+        }
+        Input{
+            vec4 modelPosition
+            vec3 modelNormal
+            vec3 modelTangent
+            mat4 boneMatrices[NumberOfBones]
+            vec4 boneWeight
+            vec4 boneIndex                    
+        }
+        Output{
+            vec4 modModelPosition 
+            vec3 modModelNormal
+            vec3 modModelTangent                   
+        }
+    }   
+}
\ No newline at end of file
diff --git a/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/basicGpuSkinning.vert b/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/basicGpuSkinning.vert
new file mode 100644
index 000000000..4c153e27f
--- /dev/null
+++ b/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/basicGpuSkinning.vert
@@ -0,0 +1,8 @@
+
+void main(){        
+        modModelPosition = (mat4(0.0) +
+            boneMatrices[int(boneIndex.x)] * boneWeight.x +
+            boneMatrices[int(boneIndex.y)] * boneWeight.y +
+            boneMatrices[int(boneIndex.z)] * boneWeight.z +
+            boneMatrices[int(boneIndex.w)] * boneWeight.w) * vec4(modelPosition.xyz,1.0);
+}
\ No newline at end of file
diff --git a/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/fullGpuSkinning.vert b/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/fullGpuSkinning.vert
new file mode 100644
index 000000000..49f8a659e
--- /dev/null
+++ b/engine/src/core-data/Common/MatDefs/ShaderNodes/HardwareSkinning/fullGpuSkinning.vert
@@ -0,0 +1,12 @@
+
+void main(){
+        modModelPosition = (mat4(0.0) +
+            boneMatrices[int(boneIndex.x)] * boneWeight.x +
+            boneMatrices[int(boneIndex.y)] * boneWeight.y +
+            boneMatrices[int(boneIndex.z)] * boneWeight.z +
+            boneMatrices[int(boneIndex.w)] * boneWeight.w) * modelPosition;
+
+        mat3 rotMat = mat3(mat[0].xyz, mat[1].xyz, mat[2].xyz);
+        modModelTangent = rotMat * modelTangent;
+        modModelNormal = rotMat * modelNormal;
+}
\ No newline at end of file
diff --git a/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java b/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java
index 81f579bd6..d738b39db 100644
--- a/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java
+++ b/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java
@@ -256,7 +256,11 @@ public class ShaderNodeLoaderDelegate {
             } else if (line.startsWith("Output")) {
                 varNames = "";
                 for (Statement statement1 : statement.getContents()) {
-                    shaderNodeDefinition.getOutputs().add(readVariable(statement1));
+                    if(statement1.getLine().trim().equals("None")){
+                        shaderNodeDefinition.setNoOutput(true);
+                    }else{
+                        shaderNodeDefinition.getOutputs().add(readVariable(statement1));
+                    }
                 }
             } else {
                 throw new MatParseException("one of Type, Shader, Documentation, Input, Output", split[0], statement);
@@ -314,7 +318,10 @@ public class ShaderNodeLoaderDelegate {
             String[] split = statement.getLine().split("[ \\{]");
             if (line.startsWith("Definition")) {
                 ShaderNodeDefinition def = findDefinition(statement);
-                shaderNode.setDefinition(def);
+                shaderNode.setDefinition(def);                
+                if(def.isNoOutput()){
+                    techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(shaderNode.getName());
+                }
             } else if (line.startsWith("Condition")) {
                 String condition = line.substring(line.lastIndexOf(":") + 1).trim();
                 extractCondition(condition, statement);
@@ -325,12 +332,12 @@ public class ShaderNodeLoaderDelegate {
                     techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(mapping.getRightVariable().getNameSpace());
                     shaderNode.getInputMapping().add(mapping);
                 }
-            } else if (line.startsWith("OutputMapping")) {
+            } else if (line.startsWith("OutputMapping")) {                
                 for (Statement statement1 : statement.getContents()) {
                     VariableMapping mapping = readOutputMapping(statement1);
                     techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(shaderNode.getName());
                     shaderNode.getOutputMapping().add(mapping);
-                }
+                }               
             } else {
                 throw new MatParseException("ShaderNodeDefinition", split[0], statement);
             }
diff --git a/engine/src/core/com/jme3/shader/ShaderNodeDefinition.java b/engine/src/core/com/jme3/shader/ShaderNodeDefinition.java
index 46b5eeb71..c8c7089ad 100644
--- a/engine/src/core/com/jme3/shader/ShaderNodeDefinition.java
+++ b/engine/src/core/com/jme3/shader/ShaderNodeDefinition.java
@@ -58,6 +58,7 @@ public class ShaderNodeDefinition implements Savable {
     private List<ShaderNodeVariable> inputs = new ArrayList<ShaderNodeVariable>();
     private List<ShaderNodeVariable> outputs = new ArrayList<ShaderNodeVariable>();
     private String path = null;
+    private boolean noOutput = false;
 
     /**
      * creates a ShaderNodeDefinition
@@ -210,6 +211,14 @@ public class ShaderNodeDefinition implements Savable {
         return shadersPath;
     }
 
+    public boolean isNoOutput() {
+        return noOutput;
+    }
+
+    public void setNoOutput(boolean noOutput) {
+        this.noOutput = noOutput;
+    }
+
     
     
     /**