@ -32,37 +32,33 @@
package com.jme3.shader ;
import com.jme3.export.* ;
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.io.IOException ;
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.HashMap ;
public final class Shader extends NativeObject implements Savable {
private String language ;
public final class Shader extends NativeObject {
/ * *
* True if the shader is fully compiled & linked .
* ( e . g no GL error will be invoked if used ) .
*
* @deprecated shader language now specified per shader source . See
* { @link ShaderSource # setLanguage ( String )
* /
private boolean usable = false ;
@Deprecated
private String language ;
/ * *
* A list of all shaders currently attached .
* A list of all shader source s currently attached .
* /
private ArrayList < ShaderSource > shaderList ;
private ArrayList < ShaderSource > shaderSource List ;
/ * *
* Maps uniform name to the uniform variable .
* /
// private HashMap<String, Uniform> uniforms;
private ListMap < String , Uniform > uniforms ;
/ * *
@ -94,50 +90,32 @@ public final class Shader extends NativeObject implements Savable {
* 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 implements Savable {
public static class ShaderSource extends NativeObject {
ShaderType shaderType ;
boolean usable = false ;
String name = null ;
String source = null ;
String defines = null ;
ShaderType sourceType ;
String language ;
String name ;
String source ;
String defines ;
public ShaderSource ( ShaderType type ) {
super ( ShaderSource . class ) ;
this . shader Type = type ;
if ( type = = null )
this . source Type = type ;
if ( type = = null ) {
throw new NullPointerException ( "The shader type must be specified" ) ;
}
}
protected ShaderSource ( ShaderSource ss ) {
super ( ShaderSource . class , ss . id ) ;
this . shaderType = ss . shaderType ;
usable = false ;
name = ss . name ;
// forget source & defines
// No data needs to be copied.
// (This is a destructable clone)
}
public ShaderSource ( ) {
super ( ShaderSource . class ) ;
}
public void write ( JmeExporter ex ) throws IOException {
OutputCapsule oc = ex . getCapsule ( this ) ;
oc . write ( shaderType , "shaderType" , null ) ;
oc . write ( name , "name" , null ) ;
oc . write ( source , "source" , null ) ;
oc . write ( defines , "defines" , null ) ;
}
public void read ( JmeImporter im ) throws IOException {
InputCapsule ic = im . getCapsule ( this ) ;
shaderType = ic . readEnum ( "shaderType" , ShaderType . class , null ) ;
name = ic . readString ( "name" , null ) ;
source = ic . readString ( "source" , null ) ;
defines = ic . readString ( "defines" , null ) ;
}
public void setName ( String name ) {
this . name = name ;
}
@ -147,21 +125,33 @@ public final class Shader extends NativeObject implements Savable {
}
public ShaderType getType ( ) {
return shaderType ;
return sourceType ;
}
public String getLanguage ( ) {
return language ;
}
public void setLanguage ( String language ) {
if ( language = = null ) {
throw new NullPointerException ( "Shader language cannot be null" ) ;
}
this . language = language ;
setUpdateNeeded ( ) ;
}
public void setSource ( String source ) {
if ( source = = null )
if ( source = = null ) {
throw new NullPointerException ( "Shader source cannot be null" ) ;
}
this . source = source ;
setUpdateNeeded ( ) ;
}
public void setDefines ( String defines ) {
if ( defines = = null )
if ( defines = = null ) {
throw new NullPointerException ( "Shader defines cannot be null" ) ;
}
this . defines = defines ;
setUpdateNeeded ( ) ;
}
@ -174,14 +164,6 @@ public final class Shader extends NativeObject implements Savable {
return defines ;
}
public boolean isUsable ( ) {
return usable ;
}
public void setUsable ( boolean usable ) {
this . usable = usable ;
}
@Override
public String toString ( ) {
String nameTxt = "" ;
@ -192,12 +174,11 @@ public final class Shader extends NativeObject implements Savable {
return getClass ( ) . getSimpleName ( ) + "[" + nameTxt + "type="
+ shader Type . name ( ) + "]" ;
+ source Type . name ( ) + ", language=" + language + "]" ;
}
public void resetObject ( ) {
id = - 1 ;
usable = false ;
setUpdateNeeded ( ) ;
}
@ -211,110 +192,103 @@ public final class Shader extends NativeObject implements Savable {
}
/ * *
* Create an empty shader .
* @deprecated Shader sources are now associated with the shader
* language .
* /
@Deprecated
public Shader ( String language ) {
super ( Shader . class ) ;
this . language = language ;
shaderList = new ArrayList < ShaderSource > ( ) ;
// uniforms = new HashMap<String, Uniform>();
initialize ( ) ;
}
/ * *
* 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 > ( ) ;
}
/ * *
* Do not use this constructor . Serialization purposes only .
* Creates a new shader , { @link # initialize ( ) } must be called
* after this constructor for the shader to be usable .
* /
public Shader ( ) {
super ( Shader . class ) ;
}
/ * *
* Do not use this constructor . Used for destructable clones only .
* /
protected Shader ( Shader s ) {
super ( Shader . class , s . id ) ;
shaderList = new ArrayList < ShaderSource > ( ) ;
//uniforms = new ListMap<String, Uniform>();
//attribs = new IntMap<Attribute>();
// NOTE: Because ShaderSources are registered separately with
// the GLObjectManager
for ( ShaderSource source : s . shaderList ) {
shaderList . add ( ( ShaderSource ) source . createDestructableClone ( ) ) ;
}
}
public void write ( JmeExporter ex ) throws IOException {
OutputCapsule oc = ex . getCapsule ( this ) ;
oc . write ( language , "language" , null ) ;
oc . writeSavableArrayList ( shaderList , "shaderList" , null ) ;
oc . writeIntSavableMap ( attribs , "attribs" , null ) ;
oc . writeStringSavableMap ( uniforms , "uniforms" , null ) ;
}
public void read ( JmeImporter im ) throws IOException {
InputCapsule ic = im . getCapsule ( this ) ;
language = ic . readString ( "language" , null ) ;
shaderList = ic . readSavableArrayList ( "shaderList" , null ) ;
attribs = ( IntMap < Attribute > ) ic . readIntSavableMap ( "attribs" , null ) ;
HashMap < String , Uniform > uniMap = ( HashMap < String , Uniform > ) ic . readStringSavableMap ( "uniforms" , null ) ;
uniforms = new ListMap < String , Uniform > ( uniMap ) ;
// 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 ( ) ) ;
}
}
/ * *
* Creates a deep clone of the shader , where the sources are available
* but have not been compiled yet . Does not copy the uniforms or attribs .
* @return
* @deprecated Use the method that takes a language argument instead .
* { @link # addSource ( com . jme3 . shader . Shader . ShaderType , java . lang . String , java . lang . String , java . lang . String , java . lang . String ) }
* /
// public Shader createDeepClone(String defines){
// Shader newShader = new Shader(language);
// for (ShaderSource source : shaderList){
// if (!source.getDefines().equals(defines)){
// // need to clone the shadersource so
// // the correct defines can be placed
// ShaderSource newSource = new ShaderSource(source.getType());
// newSource.setSource(source.getSource());
// newSource.setDefines(defines);
// newShader.addSource(newSource);
// }else{
// // no need to clone source, also saves
// // having to compile the shadersource
// newShader.addSource(source);
// }
// }
// return newShader;
// }
@Deprecated
public void addSource ( ShaderType type , String name , String source , String defines ) {
addSource ( type , name , source , defines , this . language ) ;
}
/ * *
* Adds source code to a certain pipeline .
*
* @param type The pipeline to control
* @param source The shader source code ( in GLSL ) .
* @deprecated Use the method that takes a language argument instead .
* { @link # addSource ( com . jme3 . shader . Shader . ShaderType , java . lang . String , java . lang . String , java . lang . String , java . lang . String ) }
* /
public void addSource ( ShaderType type , String name , String source , String defines ) {
ShaderSource shader = new ShaderSource ( type ) ;
shader . setSource ( source ) ;
shader . setName ( name ) ;
if ( defines ! = null )
shader . setDefines ( defines ) ;
shaderList . add ( shader ) ;
setUpdateNeeded ( ) ;
}
@Deprecated
public void addSource ( ShaderType type , String source , String defines ) {
addSource ( type , null , source , defines ) ;
}
/ * *
* @deprecated Use the method that takes a language argument instead .
* { @link # addSource ( com . jme3 . shader . Shader . ShaderType , java . lang . String , java . lang . String , java . lang . String , java . lang . String ) }
* /
@Deprecated
public void addSource ( ShaderType type , String source ) {
addSource ( type , source , null ) ;
}
/ * *
* Adds an existing shader source to this shader .
* @param source
* @deprecated Shader sources may not be shared .
* { @link # addSource ( com . jme3 . shader . Shader . ShaderType , java . lang . String , java . lang . String , java . lang . String , java . lang . String ) }
* /
@Deprecated
private void addSource ( ShaderSource source ) {
shaderList . add ( source ) ;
shaderSourceList . add ( source ) ;
setUpdateNeeded ( ) ;
}
/ * *
* 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 ( ) ;
}
@ -343,69 +317,73 @@ public final class Shader extends NativeObject implements Savable {
return attrib ;
}
// public Collection<Uniform> getUniforms(){
// return uniforms.values();
// }
public ListMap < String , Uniform > getUniformMap ( ) {
return uniforms ;
}
// public Collection<Attribute> getAttributes() {
// return attribs.
// }
public Collection < ShaderSource > getSources ( ) {
return shaderList ;
return shaderSourceList ;
}
/ * *
* @deprecated Shaders no longer have a language variable ,
* use { @link ShaderSource # getLanguage ( ) } instead .
* /
@Deprecated
public String getLanguage ( ) {
return language ;
}
@Override
public String toString ( ) {
return getClass ( ) . getSimpleName ( ) + "[language=" + language
+ ", numSources=" + shader List . size ( )
+ ", numUniforms=" + uniforms . size ( )
+ ", shaderSources=" + getSources ( ) + "]" ;
public String toString ( ) {
return getClass ( ) . getSimpleName ( ) +
"[numSources=" + shaderSource List. size ( ) +
", numUniforms=" + uniforms . size ( ) +
", shaderSources=" + getSources ( ) + "]" ;
}
/ * *
* Clears all sources . Assuming that they have already been detached and
* removed on the GL side .
* @deprecated This method is not needed since deleting
* a shader causes the sources to delete as well , thus its not required
* for them to be GC ' d to be removed from GL .
* /
@Deprecated
public void resetSources ( ) {
shaderList . clear ( ) ;
shaderSource List . clear ( ) ;
}
/ * *
* Returns true if this program and all it ' s shaders have been compiled ,
* linked and validated successfuly .
* @deprecated Unusable shaders cause the renderer to crash ,
* therefore this field no longer serves any purpose .
* /
@Deprecated
public boolean isUsable ( ) {
return usabl e;
return tru e;
}
/ * *
* Sets if the program can be used . Should only be called by the Renderer .
* @param usable
* @deprecated Unusable shaders cause the renderer to crash ,
* therefore this field no longer serves any purpose .
* /
@Deprecated
public void setUsable ( boolean usable ) {
this . usable = usable ;
}
/ * *
* Usually called when the shader itself changes or during any
* time when the var locations need to be refreshed .
* time when the variable locations need to be refreshed .
* /
public void resetLocations ( ) {
// NOTE: Shader sources will be reset seperately from the shader itself.
for ( Uniform uniform : uniforms . values ( ) ) {
uniform . reset ( ) ; // fixes issue with re-initialization
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
}
}
for ( Entry < Attribute > entry : attribs ) {
entry . getValue ( ) . location = - 2 ;
if ( attribs ! = null ) {
for ( Entry < Attribute > entry : attribs ) {
entry . getValue ( ) . location = ShaderVariable . LOC_UNKNOWN ;
}
}
}
@ -422,12 +400,9 @@ public final class Shader extends NativeObject implements Savable {
@Override
public void resetObject ( ) {
this . id = - 1 ;
this . usable = false ;
for ( ShaderSource source : shaderList ) {
for ( ShaderSource source : shaderSourceList ) {
source . resetObject ( ) ;
}
setUpdateNeeded ( ) ;
}