* Shader now stores shader language in the ShaderSources instead of the Shader itself (everything makes a lot more sense now).

^ Make sure your shader languages are appropriate for each shader type (vert / frag) in your J3MS!
 * Shaders no longer have the "usable" member and the renderers don't use it either (its useless)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9545 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Sha..rd 13 years ago
parent af7435ffdf
commit 55d75c5abc
  1. 134
      engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
  2. 7
      engine/src/core-effects/Common/MatDefs/Post/BloomFinal.j3md
  3. 48
      engine/src/core/com/jme3/asset/DesktopAssetManager.java
  4. 13
      engine/src/core/com/jme3/material/Technique.java
  5. 68
      engine/src/core/com/jme3/material/TechniqueDef.java
  6. 297
      engine/src/core/com/jme3/shader/Shader.java
  7. 27
      engine/src/core/com/jme3/shader/ShaderKey.java
  8. 19
      engine/src/core/com/jme3/shader/ShaderVariable.java
  9. 134
      engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java

@ -590,6 +590,18 @@ public class OGLESShaderRenderer implements Renderer {
} }
} }
protected void bindProgram(Shader shader) {
int shaderId = shader.getId();
if (context.boundShaderProgram != shaderId) {
GLES20.glUseProgram(shaderId);
statistics.onShaderUse(shader, true);
boundShader = shader;
context.boundShaderProgram = shaderId;
} else {
statistics.onShaderUse(shader, false);
}
}
protected void updateUniform(Shader shader, Uniform uniform) { protected void updateUniform(Shader shader, Uniform uniform) {
int shaderId = shader.getId(); int shaderId = shader.getId();
@ -698,7 +710,6 @@ public class OGLESShaderRenderer implements Renderer {
protected void updateShaderUniforms(Shader shader) { protected void updateShaderUniforms(Shader shader) {
ListMap<String, Uniform> uniforms = shader.getUniformMap(); ListMap<String, Uniform> uniforms = shader.getUniformMap();
// for (Uniform uniform : shader.getUniforms()){
for (int i = 0; i < uniforms.size(); i++) { for (int i = 0; i < uniforms.size(); i++) {
Uniform uniform = uniforms.getValue(i); Uniform uniform = uniforms.getValue(i);
if (uniform.isUpdateNeeded()) { if (uniform.isUpdateNeeded()) {
@ -709,7 +720,6 @@ public class OGLESShaderRenderer implements Renderer {
protected void resetUniformLocations(Shader shader) { protected void resetUniformLocations(Shader shader) {
ListMap<String, Uniform> uniforms = shader.getUniformMap(); ListMap<String, Uniform> uniforms = shader.getUniformMap();
// for (Uniform uniform : shader.getUniforms()){
for (int i = 0; i < uniforms.size(); i++) { for (int i = 0; i < uniforms.size(); i++) {
Uniform uniform = uniforms.getValue(i); Uniform uniform = uniforms.getValue(i);
uniform.reset(); // e.g check location again uniform.reset(); // e.g check location again
@ -736,27 +746,28 @@ public class OGLESShaderRenderer implements Renderer {
} }
} }
public void updateShaderSourceData(ShaderSource source, String language) { public void updateShaderSourceData(ShaderSource source) {
int id = source.getId(); int id = source.getId();
if (id == -1) { if (id == -1) {
// create id // Create id
id = GLES20.glCreateShader(convertShaderType(source.getType())); id = GLES20.glCreateShader(convertShaderType(source.getType()));
if (id <= 0) { if (id <= 0) {
throw new RendererException("Invalid ID received when trying to create shader."); throw new RendererException("Invalid ID received when trying to create shader.");
} }
source.setId(id); source.setId(id);
} }
if (!source.getLanguage().equals("GLSL100")) {
throw new RendererException("This shader cannot run in OpenGL ES. "
+ "Only GLSL 1.0 shaders are supported.");
}
// upload shader source // upload shader source
// merge the defines and source code // merge the defines and source code
byte[] versionData = new byte[]{};//"#version 140\n".getBytes();
// versionData = "#define INSTANCING 1\n".getBytes();
byte[] definesCodeData = source.getDefines().getBytes(); byte[] definesCodeData = source.getDefines().getBytes();
byte[] sourceCodeData = source.getSource().getBytes(); byte[] sourceCodeData = source.getSource().getBytes();
ByteBuffer codeBuf = BufferUtils.createByteBuffer(versionData.length ByteBuffer codeBuf = BufferUtils.createByteBuffer(definesCodeData.length
+ definesCodeData.length + sourceCodeData.length);
+ sourceCodeData.length);
codeBuf.put(versionData);
codeBuf.put(definesCodeData); codeBuf.put(definesCodeData);
codeBuf.put(sourceCodeData); codeBuf.put(sourceCodeData);
codeBuf.flip(); codeBuf.flip();
@ -791,10 +802,11 @@ public class OGLESShaderRenderer implements Renderer {
if (compiledOK) { if (compiledOK) {
if (infoLog != null) { if (infoLog != null) {
logger.log(Level.INFO, "compile success: " + source.getName() + ", " + infoLog); logger.log(Level.INFO, "compile success: {0}, {1}", new Object[]{source.getName(), infoLog});
} else { } else {
logger.log(Level.FINE, "compile success: " + source.getName()); logger.log(Level.FINE, "compile success: {0}", source.getName());
} }
source.clearUpdateNeeded();
} else { } else {
logger.log(Level.WARNING, "Bad compile of:\n{0}", logger.log(Level.WARNING, "Bad compile of:\n{0}",
new Object[]{ShaderDebug.formatShaderSource(source.getDefines(), source.getSource(),stringBuf.toString())}); new Object[]{ShaderDebug.formatShaderSource(source.getDefines(), source.getSource(),stringBuf.toString())});
@ -804,18 +816,6 @@ public class OGLESShaderRenderer implements Renderer {
throw new RendererException("compile error in:" + source + " error: <not provided>"); throw new RendererException("compile error in:" + source + " error: <not provided>");
} }
} }
source.clearUpdateNeeded();
// only usable if compiled
source.setUsable(compiledOK);
if (!compiledOK) {
// make sure to dispose id cause all program's
// shaders will be cleared later.
GLES20.glDeleteShader(id);
} else {
// register for cleanup since the ID is usable
objManager.registerForCleanup(source);
}
} }
public void updateShaderData(Shader shader) { public void updateShaderData(Shader shader) {
@ -835,15 +835,7 @@ public class OGLESShaderRenderer implements Renderer {
for (ShaderSource source : shader.getSources()) { for (ShaderSource source : shader.getSources()) {
if (source.isUpdateNeeded()) { if (source.isUpdateNeeded()) {
updateShaderSourceData(source, shader.getLanguage()); updateShaderSourceData(source);
// shader has been compiled here
}
if (!source.isUsable()) {
// it's useless.. just forget about everything..
shader.setUsable(false);
shader.clearUpdateNeeded();
return;
} }
GLES20.glAttachShader(id, source.getId()); GLES20.glAttachShader(id, source.getId());
} }
@ -871,41 +863,27 @@ public class OGLESShaderRenderer implements Renderer {
} else { } else {
logger.fine("shader link success"); logger.fine("shader link success");
} }
} else { shader.clearUpdateNeeded();
if (infoLog != null) {
throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
} else {
throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
}
}
shader.clearUpdateNeeded();
if (!linkOK) {
// failure.. forget about everything
shader.resetSources();
shader.setUsable(false);
deleteShader(shader);
} else {
shader.setUsable(true);
if (needRegister) { if (needRegister) {
// Register shader for clean up if it was created in this method.
objManager.registerForCleanup(shader); objManager.registerForCleanup(shader);
statistics.onNewShader(); statistics.onNewShader();
} else { } else {
// OpenGL spec: uniform locations may change after re-link // OpenGL spec: uniform locations may change after re-link
resetUniformLocations(shader); resetUniformLocations(shader);
} }
} else {
if (infoLog != null) {
throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
} else {
throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
}
} }
} }
public void setShader(Shader shader) { public void setShader(Shader shader) {
if (shader == null) { if (shader == null) {
if (context.boundShaderProgram > 0) { throw new IllegalArgumentException("Shader cannot be null");
GLES20.glUseProgram(0);
statistics.onShaderUse(null, true);
context.boundShaderProgram = 0;
boundShader = null;
}
} else { } else {
if (shader.isUpdateNeeded()) { if (shader.isUpdateNeeded()) {
updateShaderData(shader); updateShaderData(shader);
@ -913,37 +891,11 @@ public class OGLESShaderRenderer implements Renderer {
// NOTE: might want to check if any of the // NOTE: might want to check if any of the
// sources need an update? // sources need an update?
if (!shader.isUsable()) {
logger.warning("shader is not usable.");
return;
}
assert shader.getId() > 0; assert shader.getId() > 0;
updateShaderUniforms(shader); updateShaderUniforms(shader);
if (context.boundShaderProgram != shader.getId()) { bindProgram(shader);
if (VALIDATE_SHADER) {
// check if shader can be used
// with current state
GLES20.glValidateProgram(shader.getId());
GLES20.glGetProgramiv(shader.getId(), GLES20.GL_VALIDATE_STATUS, intBuf1);
boolean validateOK = intBuf1.get(0) == GLES20.GL_TRUE;
if (validateOK) {
logger.fine("shader validate success");
} else {
logger.warning("shader validate failure");
}
}
GLES20.glUseProgram(shader.getId());
statistics.onShaderUse(shader, true);
context.boundShaderProgram = shader.getId();
boundShader = shader;
} else {
statistics.onShaderUse(shader, false);
}
} }
} }
@ -952,9 +904,8 @@ public class OGLESShaderRenderer implements Renderer {
logger.warning("Shader source is not uploaded to GPU, cannot delete."); logger.warning("Shader source is not uploaded to GPU, cannot delete.");
return; return;
} }
source.setUsable(false);
source.clearUpdateNeeded(); source.clearUpdateNeeded();
GLES20.glDeleteShader(source.getId()); GLES20.glDeleteShader(source.getId());
source.resetObject(); source.resetObject();
} }
@ -964,20 +915,17 @@ public class OGLESShaderRenderer implements Renderer {
logger.warning("Shader is not uploaded to GPU, cannot delete."); logger.warning("Shader is not uploaded to GPU, cannot delete.");
return; return;
} }
for (ShaderSource source : shader.getSources()) { for (ShaderSource source : shader.getSources()) {
if (source.getId() != -1) { if (source.getId() != -1) {
GLES20.glDetachShader(shader.getId(), source.getId()); GLES20.glDetachShader(shader.getId(), source.getId());
// the next part is done by the GLObjectManager automatically deleteShaderSource(source);
// glDeleteShader(source.getId());
} }
} }
// kill all references so sources can be collected
// if needed.
shader.resetSources();
GLES20.glDeleteProgram(shader.getId()); GLES20.glDeleteProgram(shader.getId());
statistics.onDeleteShader(); statistics.onDeleteShader();
shader.resetObject();
} }
/*********************************************************************\ /*********************************************************************\

@ -8,7 +8,7 @@ MaterialDef Bloom Final {
} }
Technique { Technique {
VertexShader GLSL100: Common/MatDefs/Post/Post15.vert VertexShader GLSL150: Common/MatDefs/Post/Post15.vert
FragmentShader GLSL150: Common/MatDefs/Post/bloomFinal15.frag FragmentShader GLSL150: Common/MatDefs/Post/bloomFinal15.frag
WorldParameters { WorldParameters {
@ -28,9 +28,4 @@ MaterialDef Bloom Final {
WorldViewProjectionMatrix WorldViewProjectionMatrix
} }
} }
Technique FixedFunc {
}
} }

@ -336,11 +336,6 @@ public class DesktopAssetManager implements AssetManager {
return loadAsset(new AssetKey(name)); return loadAsset(new AssetKey(name));
} }
/**
* Loads a texture.
*
* @return the texture
*/
public Texture loadTexture(TextureKey key){ public Texture loadTexture(TextureKey key){
return (Texture) loadAsset(key); return (Texture) loadAsset(key);
} }
@ -365,18 +360,16 @@ public class DesktopAssetManager implements AssetManager {
return loadAudio(new AudioKey(name, false)); return loadAudio(new AudioKey(name, false));
} }
/**
* Loads a bitmap font with the given name.
*
* @param name
* @return the loaded {@link BitmapFont}
*/
public BitmapFont loadFont(String name){ public BitmapFont loadFont(String name){
return (BitmapFont) loadAsset(new AssetKey(name)); return (BitmapFont) loadAsset(new AssetKey(name));
} }
public InputStream loadGLSLLibrary(AssetKey key){ public Spatial loadModel(ModelKey key){
return (InputStream) loadAsset(key); return (Spatial) loadAsset(key);
}
public Spatial loadModel(String name){
return loadModel(new ModelKey(name));
} }
/** /**
@ -389,34 +382,21 @@ public class DesktopAssetManager implements AssetManager {
// cache abuse in method // cache abuse in method
// that doesn't use loaders/locators // that doesn't use loaders/locators
AssetCache cache = handler.getCache(SimpleAssetCache.class); AssetCache cache = handler.getCache(SimpleAssetCache.class);
Shader s = (Shader) cache.getFromCache(key); Shader shader = (Shader) cache.getFromCache(key);
if (s == null){ if (shader == null){
String vertName = key.getVertName(); String vertName = key.getVertName();
String fragName = key.getFragName(); String fragName = key.getFragName();
String vertSource = (String) loadAsset(new AssetKey(vertName)); String vertSource = (String) loadAsset(new AssetKey(vertName));
String fragSource = (String) loadAsset(new AssetKey(fragName)); String fragSource = (String) loadAsset(new AssetKey(fragName));
s = new Shader(key.getLanguage()); shader = new Shader();
s.addSource(Shader.ShaderType.Vertex, vertName, vertSource, key.getDefines().getCompiled()); shader.initialize();
s.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled()); shader.addSource(Shader.ShaderType.Vertex, vertName, vertSource, key.getDefines().getCompiled(), key.getVertexShaderLanguage());
shader.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled(), key.getFragmentShaderLanguage());
cache.addToCache(key, s); cache.addToCache(key, shader);
} }
return s; return shader;
}
public Spatial loadModel(ModelKey key){
return (Spatial) loadAsset(key);
}
/**
* Load a model.
*
* @param name
* @return the loaded model
*/
public Spatial loadModel(String name){
return loadModel(new ModelKey(name));
} }
} }

@ -32,9 +32,7 @@
package com.jme3.material; package com.jme3.material;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.export.*;
import com.jme3.shader.*; import com.jme3.shader.*;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -43,7 +41,7 @@ import java.util.logging.Logger;
/** /**
* Represents a technique instance. * Represents a technique instance.
*/ */
public class Technique implements Savable { public class Technique /* implements Savable */ {
private static final Logger logger = Logger.getLogger(Technique.class.getName()); private static final Logger logger = Logger.getLogger(Technique.class.getName());
private TechniqueDef def; private TechniqueDef def;
@ -133,6 +131,10 @@ public class Technique implements Savable {
} }
void updateUniformParam(String paramName, VarType type, Object value) { void updateUniformParam(String paramName, VarType type, Object value) {
if (paramName == null) {
throw new IllegalArgumentException();
}
Uniform u = shader.getUniform(paramName); Uniform u = shader.getUniform(paramName);
switch (type) { switch (type) {
case TextureBuffer: case TextureBuffer:
@ -208,7 +210,8 @@ public class Technique implements Savable {
ShaderKey key = new ShaderKey(def.getVertexShaderName(), ShaderKey key = new ShaderKey(def.getVertexShaderName(),
def.getFragmentShaderName(), def.getFragmentShaderName(),
allDefines, allDefines,
def.getShaderLanguage()); def.getVertexShaderLanguage(),
def.getFragmentShaderLanguage());
shader = manager.loadShader(key); shader = manager.loadShader(key);
// register the world bound uniforms // register the world bound uniforms
@ -225,6 +228,7 @@ public class Technique implements Savable {
needReload = false; needReload = false;
} }
/*
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(def, "def", null); oc.write(def, "def", null);
@ -240,4 +244,5 @@ public class Technique implements Savable {
defines = (DefineList) ic.readSavable("defines", null); defines = (DefineList) ic.readSavable("defines", null);
shader = (Shader) ic.readSavable("shader", null); shader = (Shader) ic.readSavable("shader", null);
} }
*/
} }

@ -51,6 +51,11 @@ import java.util.List;
*/ */
public class TechniqueDef implements Savable { public class TechniqueDef implements Savable {
/**
* Version #1: Separate shader language for each shader source.
*/
public static final int SAVABLE_VERSION = 1;
/** /**
* Describes light rendering mode. * Describes light rendering mode.
*/ */
@ -101,7 +106,9 @@ public class TechniqueDef implements Savable {
private String vertName; private String vertName;
private String fragName; private String fragName;
private String shaderLang; private String vertLanguage;
private String fragLanguage;
private DefineList presetDefines; private DefineList presetDefines;
private boolean usesShaders; private boolean usesShaders;
@ -227,13 +234,16 @@ public class TechniqueDef implements Savable {
* @param fragmentShader The name of the fragment shader * @param fragmentShader The name of the fragment shader
* @param shaderLanguage The shader language * @param shaderLanguage The shader language
*/ */
public void setShaderFile(String vertexShader, String fragmentShader, String shaderLanguage){ public void setShaderFile(String vertexShader, String fragmentShader, String vertLanguage, String fragLanguage){
this.vertName = vertexShader; this.vertName = vertexShader;
this.fragName = fragmentShader; this.fragName = fragmentShader;
this.shaderLang = shaderLanguage; this.vertLanguage = vertLanguage;
this.fragLanguage = fragLanguage;
Caps langCap = Caps.valueOf(shaderLanguage); Caps vertCap = Caps.valueOf(vertLanguage);
requiredCaps.add(langCap); requiredCaps.add(vertCap);
Caps fragCap = Caps.valueOf(fragLanguage);
requiredCaps.add(fragCap);
usesShaders = true; usesShaders = true;
} }
@ -247,9 +257,9 @@ public class TechniqueDef implements Savable {
* @see #addShaderParamDefine(java.lang.String, java.lang.String) * @see #addShaderParamDefine(java.lang.String, java.lang.String)
*/ */
public String getShaderParamDefine(String paramName){ public String getShaderParamDefine(String paramName){
if (defineParams == null) if (defineParams == null) {
return null; return null;
}
return defineParams.get(paramName); return defineParams.get(paramName);
} }
@ -266,9 +276,9 @@ public class TechniqueDef implements Savable {
* @param defineName The name of the define parameter, e.g. USE_LIGHTING * @param defineName The name of the define parameter, e.g. USE_LIGHTING
*/ */
public void addShaderParamDefine(String paramName, String defineName){ public void addShaderParamDefine(String paramName, String defineName){
if (defineParams == null) if (defineParams == null) {
defineParams = new HashMap<String, String>(); defineParams = new HashMap<String, String>();
}
defineParams.put(paramName, defineName); defineParams.put(paramName, defineName);
} }
@ -297,9 +307,9 @@ public class TechniqueDef implements Savable {
* @param value The value of the define * @param value The value of the define
*/ */
public void addShaderPresetDefine(String defineName, VarType type, Object value){ public void addShaderPresetDefine(String defineName, VarType type, Object value){
if (presetDefines == null) if (presetDefines == null) {
presetDefines = new DefineList(); presetDefines = new DefineList();
}
presetDefines.set(defineName, type, value); presetDefines.set(defineName, type, value);
} }
@ -325,14 +335,27 @@ public class TechniqueDef implements Savable {
} }
/** /**
* Returns the shader language of the shaders used in this technique. * @deprecated Use {@link #getVertexShaderLanguage() } instead.
*
* @return the shader language of the shaders used in this technique.
*/ */
@Deprecated
public String getShaderLanguage() { public String getShaderLanguage() {
return shaderLang; return vertLanguage;
} }
/**
* Returns the language of the fragment shader used in this technique.
*/
public String getFragmentShaderLanguage() {
return fragLanguage;
}
/**
* Returns the language of the vertex shader used in this technique.
*/
public String getVertexShaderLanguage() {
return vertLanguage;
}
/** /**
* Adds a new world parameter by the given name. * Adds a new world parameter by the given name.
* *
@ -368,12 +391,14 @@ public class TechniqueDef implements Savable {
oc.write(name, "name", null); oc.write(name, "name", null);
oc.write(vertName, "vertName", null); oc.write(vertName, "vertName", null);
oc.write(fragName, "fragName", null); oc.write(fragName, "fragName", null);
oc.write(shaderLang, "shaderLang", null); oc.write(vertLanguage, "vertLanguage", null);
oc.write(vertLanguage, "fragLanguage", null);
oc.write(presetDefines, "presetDefines", null); oc.write(presetDefines, "presetDefines", null);
oc.write(lightMode, "lightMode", LightMode.Disable); oc.write(lightMode, "lightMode", LightMode.Disable);
oc.write(shadowMode, "shadowMode", ShadowMode.Disable); oc.write(shadowMode, "shadowMode", ShadowMode.Disable);
oc.write(renderState, "renderState", null); oc.write(renderState, "renderState", null);
oc.write(usesShaders, "usesShaders", false); oc.write(usesShaders, "usesShaders", false);
// TODO: Finish this when Map<String, String> export is available // TODO: Finish this when Map<String, String> export is available
// oc.write(defineParams, "defineParams", null); // oc.write(defineParams, "defineParams", null);
// TODO: Finish this when List<Enum> export is available // TODO: Finish this when List<Enum> export is available
@ -385,12 +410,21 @@ public class TechniqueDef implements Savable {
name = ic.readString("name", null); name = ic.readString("name", null);
vertName = ic.readString("vertName", null); vertName = ic.readString("vertName", null);
fragName = ic.readString("fragName", null); fragName = ic.readString("fragName", null);
shaderLang = ic.readString("shaderLang", null);
presetDefines = (DefineList) ic.readSavable("presetDefines", null); presetDefines = (DefineList) ic.readSavable("presetDefines", null);
lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable); lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable);
shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable); shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable);
renderState = (RenderState) ic.readSavable("renderState", null); renderState = (RenderState) ic.readSavable("renderState", null);
usesShaders = ic.readBoolean("usesShaders", false); usesShaders = ic.readBoolean("usesShaders", false);
if (ic.getSavableVersion(TechniqueDef.class) == 0) {
// Old version
vertLanguage = ic.readString("shaderLang", null);
fragLanguage = vertLanguage;
} else {
// New version
vertLanguage = ic.readString("vertLanguage", null);
fragLanguage = ic.readString("fragLanguage", null);;
}
} }
} }

@ -32,37 +32,33 @@
package com.jme3.shader; package com.jme3.shader;
import com.jme3.export.*;
import com.jme3.renderer.Renderer; import com.jme3.renderer.Renderer;
import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer;
import com.jme3.util.IntMap; import com.jme3.util.IntMap;
import com.jme3.util.IntMap.Entry; import com.jme3.util.IntMap.Entry;
import com.jme3.util.ListMap; import com.jme3.util.ListMap;
import com.jme3.util.NativeObject; import com.jme3.util.NativeObject;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
public final class Shader extends NativeObject implements Savable { public final class Shader extends NativeObject {
private String language;
/** /**
* 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 sources currently attached.
*/ */
private ArrayList<ShaderSource> shaderList; private ArrayList<ShaderSource> shaderSourceList;
/** /**
* Maps uniform name to the uniform variable. * Maps uniform name to the uniform variable.
*/ */
// private HashMap<String, Uniform> uniforms;
private ListMap<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 * Shader source describes a shader object in OpenGL. Each shader source
* is assigned a certain pipeline which it controls (described by it's type). * 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; ShaderType sourceType;
String language;
boolean usable = false; String name;
String name = null; String source;
String source = null; String defines;
String defines = null;
public ShaderSource(ShaderType type){ public ShaderSource(ShaderType type){
super(ShaderSource.class); super(ShaderSource.class);
this.shaderType = type; this.sourceType = type;
if (type == null) if (type == null) {
throw new NullPointerException("The shader type must be specified"); throw new NullPointerException("The shader type must be specified");
}
} }
protected ShaderSource(ShaderSource ss){ protected ShaderSource(ShaderSource ss){
super(ShaderSource.class, ss.id); super(ShaderSource.class, ss.id);
this.shaderType = ss.shaderType; // No data needs to be copied.
usable = false; // (This is a destructable clone)
name = ss.name;
// forget source & defines
} }
public ShaderSource(){ public ShaderSource(){
super(ShaderSource.class); 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){ public void setName(String name){
this.name = name; this.name = name;
} }
@ -147,21 +125,33 @@ public final class Shader extends NativeObject implements Savable {
} }
public ShaderType getType() { 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){ public void setSource(String source){
if (source == null) if (source == null) {
throw new NullPointerException("Shader source cannot be null"); throw new NullPointerException("Shader source cannot be null");
}
this.source = source; this.source = source;
setUpdateNeeded(); setUpdateNeeded();
} }
public void setDefines(String defines){ public void setDefines(String defines){
if (defines == null) if (defines == null) {
throw new NullPointerException("Shader defines cannot be null"); throw new NullPointerException("Shader defines cannot be null");
}
this.defines = defines; this.defines = defines;
setUpdateNeeded(); setUpdateNeeded();
} }
@ -174,14 +164,6 @@ public final class Shader extends NativeObject implements Savable {
return defines; return defines;
} }
public boolean isUsable(){
return usable;
}
public void setUsable(boolean usable){
this.usable = usable;
}
@Override @Override
public String toString(){ public String toString(){
String nameTxt = ""; String nameTxt = "";
@ -192,12 +174,11 @@ public final class Shader extends NativeObject implements Savable {
return getClass().getSimpleName() + "["+nameTxt+"type=" return getClass().getSimpleName() + "["+nameTxt+"type="
+ shaderType.name()+"]"; + sourceType.name()+", language=" + language + "]";
} }
public void resetObject(){ public void resetObject(){
id = -1; id = -1;
usable = false;
setUpdateNeeded(); 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){ public Shader(String language){
super(Shader.class); super(Shader.class);
this.language = language; this.language = language;
shaderList = new ArrayList<ShaderSource>(); initialize();
// uniforms = new HashMap<String, Uniform>(); }
/**
* 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>(); uniforms = new ListMap<String, Uniform>();
attribs = new IntMap<Attribute>(); 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(){ public Shader(){
super(Shader.class); super(Shader.class);
} }
/**
* Do not use this constructor. Used for destructable clones only.
*/
protected Shader(Shader s){ protected Shader(Shader s){
super(Shader.class, s.id); 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 // Shader sources cannot be shared, therefore they must
// the GLObjectManager // be destroyed together with the parent shader.
for (ShaderSource source : s.shaderList){ shaderSourceList = new ArrayList<ShaderSource>();
shaderList.add( (ShaderSource)source.createDestructableClone() ); for (ShaderSource source : s.shaderSourceList){
shaderSourceList.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);
}
/** /**
* Creates a deep clone of the shader, where the sources are available * @deprecated Use the method that takes a language argument instead.
* but have not been compiled yet. Does not copy the uniforms or attribs. * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) }
* @return
*/ */
// public Shader createDeepClone(String defines){ @Deprecated
// Shader newShader = new Shader(language); public void addSource(ShaderType type, String name, String source, String defines) {
// for (ShaderSource source : shaderList){ addSource(type, name, source, defines, this.language);
// 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;
// }
/** /**
* Adds source code to a certain pipeline. * @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) }
* @param type The pipeline to control
* @param source The shader source code (in GLSL).
*/ */
public void addSource(ShaderType type, String name, String source, String defines){ @Deprecated
ShaderSource shader = new ShaderSource(type);
shader.setSource(source);
shader.setName(name);
if (defines != null)
shader.setDefines(defines);
shaderList.add(shader);
setUpdateNeeded();
}
public void addSource(ShaderType type, String source, String defines){ public void addSource(ShaderType type, String source, String defines){
addSource(type, null, source, 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){ public void addSource(ShaderType type, String source){
addSource(type, source, null); addSource(type, source, null);
} }
/** /**
* Adds an existing shader source to this shader. * @deprecated Shader sources may not be shared.
* @param source * {@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){ 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(); setUpdateNeeded();
} }
@ -343,69 +317,73 @@ public final class Shader extends NativeObject implements Savable {
return attrib; return attrib;
} }
// public Collection<Uniform> getUniforms(){
// return uniforms.values();
// }
public ListMap<String, Uniform> getUniformMap(){ public ListMap<String, Uniform> getUniformMap(){
return uniforms; return uniforms;
} }
// public Collection<Attribute> getAttributes() {
// return attribs.
// }
public Collection<ShaderSource> getSources(){ 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(){ public String getLanguage(){
return language; return language;
} }
@Override @Override
public String toString(){ public String toString() {
return getClass().getSimpleName() + "[language="+language return getClass().getSimpleName() +
+ ", numSources="+shaderList.size() "[numSources=" + shaderSourceList.size() +
+ ", numUniforms="+uniforms.size() ", numUniforms=" + uniforms.size() +
+ ", shaderSources="+getSources()+"]"; ", shaderSources=" + getSources() + "]";
} }
/** /**
* Clears all sources. Assuming that they have already been detached and * @deprecated This method is not needed since deleting
* removed on the GL side. * 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(){ public void resetSources(){
shaderList.clear(); shaderSourceList.clear();
} }
/** /**
* Returns true if this program and all it's shaders have been compiled, * @deprecated Unusable shaders cause the renderer to crash,
* linked and validated successfuly. * therefore this field no longer serves any purpose.
*/ */
@Deprecated
public boolean isUsable(){ public boolean isUsable(){
return usable; return true;
} }
/** /**
* Sets if the program can be used. Should only be called by the Renderer. * @deprecated Unusable shaders cause the renderer to crash,
* @param usable * therefore this field no longer serves any purpose.
*/ */
@Deprecated
public void setUsable(boolean usable){ public void setUsable(boolean usable){
this.usable = usable;
} }
/** /**
* Usually called when the shader itself changes or during any * 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(){ public void resetLocations() {
// NOTE: Shader sources will be reset seperately from the shader itself. if (uniforms != null) {
for (Uniform uniform : uniforms.values()){ // NOTE: Shader sources will be reset seperately from the shader itself.
uniform.reset(); // fixes issue with re-initialization for (Uniform uniform : uniforms.values()) {
uniform.reset(); // fixes issue with re-initialization
}
} }
for (Entry<Attribute> entry : attribs){ if (attribs != null) {
entry.getValue().location = -2; for (Entry<Attribute> entry : attribs) {
entry.getValue().location = ShaderVariable.LOC_UNKNOWN;
}
} }
} }
@ -422,12 +400,9 @@ public final class Shader extends NativeObject implements Savable {
@Override @Override
public void resetObject() { public void resetObject() {
this.id = -1; this.id = -1;
this.usable = false; for (ShaderSource source : shaderSourceList){
for (ShaderSource source : shaderList){
source.resetObject(); source.resetObject();
} }
setUpdateNeeded(); setUpdateNeeded();
} }

@ -43,16 +43,18 @@ public class ShaderKey extends AssetKey<Shader> {
protected String fragName; protected String fragName;
protected DefineList defines; protected DefineList defines;
protected String language; protected String vertLanguage;
protected String fragLanguage;
public ShaderKey(){ public ShaderKey(){
} }
public ShaderKey(String vertName, String fragName, DefineList defines, String lang){ public ShaderKey(String vertName, String fragName, DefineList defines, String vertLanguage, String fragLanguage){
super(vertName); super(vertName);
this.fragName = fragName; this.fragName = fragName;
this.defines = defines; this.defines = defines;
this.language = lang; this.vertLanguage = vertLanguage;
this.fragLanguage = fragLanguage;
} }
@Override @Override
@ -71,7 +73,6 @@ public class ShaderKey extends AssetKey<Shader> {
final ShaderKey other = (ShaderKey) obj; final ShaderKey other = (ShaderKey) obj;
if (name.equals(other.name) && fragName.equals(other.fragName)){ if (name.equals(other.name) && fragName.equals(other.fragName)){
// return true;
if (defines != null && other.defines != null) if (defines != null && other.defines != null)
return defines.getCompiled().equals(other.defines.getCompiled()); return defines.getCompiled().equals(other.defines.getCompiled());
else if (defines != null || other.defines != null) else if (defines != null || other.defines != null)
@ -103,8 +104,20 @@ public class ShaderKey extends AssetKey<Shader> {
return fragName; return fragName;
} }
/**
* @deprecated Use {@link #getVertexShaderLanguage() } instead.
*/
@Deprecated
public String getLanguage() { public String getLanguage() {
return language; return vertLanguage;
}
public String getVertexShaderLanguage() {
return vertLanguage;
}
public String getFragmentShaderLanguage() {
return fragLanguage;
} }
@Override @Override
@ -112,7 +125,7 @@ public class ShaderKey extends AssetKey<Shader> {
super.write(ex); super.write(ex);
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(fragName, "fragment_name", null); oc.write(fragName, "fragment_name", null);
oc.write(language, "language", null); oc.write(vertLanguage, "language", null);
} }
@Override @Override
@ -120,7 +133,7 @@ public class ShaderKey extends AssetKey<Shader> {
super.read(im); super.read(im);
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
fragName = ic.readString("fragment_name", null); fragName = ic.readString("fragment_name", null);
language = ic.readString("language", null); vertLanguage = ic.readString("language", null);
} }
} }

@ -32,15 +32,15 @@
package com.jme3.shader; package com.jme3.shader;
import com.jme3.export.*; public class ShaderVariable {
import java.io.IOException;
public class ShaderVariable implements Savable {
public static final int LOC_UNKNOWN = -2,
LOC_NOT_DEFINED = -1;
// if -2, location not known // if -2, location not known
// if -1, not defined in shader // if -1, not defined in shader
// if >= 0, uniform defined and available. // if >= 0, uniform defined and available.
protected int location = -2; protected int location = LOC_UNKNOWN;
/** /**
* Name of the uniform as was declared in the shader. * Name of the uniform as was declared in the shader.
@ -54,15 +54,6 @@ public class ShaderVariable implements Savable {
*/ */
protected boolean updateNeeded = true;; protected boolean updateNeeded = true;;
public void write(JmeExporter ex) throws IOException{
OutputCapsule oc = ex.getCapsule(this);
oc.write(name, "name", null);
}
public void read(JmeImporter im) throws IOException{
InputCapsule ic = im.getCapsule(this);
name = ic.readString("name", null);
}
public void setLocation(int location){ public void setLocation(int location){
this.location = location; this.location = location;

@ -53,7 +53,10 @@ import com.jme3.texture.FrameBuffer.RenderBuffer;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapAxis; import com.jme3.texture.Texture.WrapAxis;
import com.jme3.util.*; import com.jme3.util.BufferUtils;
import com.jme3.util.ListMap;
import com.jme3.util.NativeObjectManager;
import com.jme3.util.SafeArrayList;
import java.nio.*; import java.nio.*;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
@ -61,7 +64,6 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import jme3tools.converters.MipMapGenerator; import jme3tools.converters.MipMapGenerator;
import jme3tools.shader.ShaderDebug; import jme3tools.shader.ShaderDebug;
import org.lwjgl.opengl.*;
import static org.lwjgl.opengl.ARBTextureMultisample.*; import static org.lwjgl.opengl.ARBTextureMultisample.*;
import static org.lwjgl.opengl.EXTFramebufferBlit.*; import static org.lwjgl.opengl.EXTFramebufferBlit.*;
import static org.lwjgl.opengl.EXTFramebufferMultisample.*; import static org.lwjgl.opengl.EXTFramebufferMultisample.*;
@ -72,6 +74,7 @@ import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*; import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.opengl.*;
//import static org.lwjgl.opengl.ARBDrawInstanced.*; //import static org.lwjgl.opengl.ARBDrawInstanced.*;
public class LwjglRenderer implements Renderer { public class LwjglRenderer implements Renderer {
@ -889,7 +892,6 @@ public class LwjglRenderer implements Renderer {
protected void updateShaderUniforms(Shader shader) { protected void updateShaderUniforms(Shader shader) {
ListMap<String, Uniform> uniforms = shader.getUniformMap(); ListMap<String, Uniform> uniforms = shader.getUniformMap();
// for (Uniform uniform : shader.getUniforms()){
for (int i = 0; i < uniforms.size(); i++) { for (int i = 0; i < uniforms.size(); i++) {
Uniform uniform = uniforms.getValue(i); Uniform uniform = uniforms.getValue(i);
if (uniform.isUpdateNeeded()) { if (uniform.isUpdateNeeded()) {
@ -900,7 +902,6 @@ public class LwjglRenderer implements Renderer {
protected void resetUniformLocations(Shader shader) { protected void resetUniformLocations(Shader shader) {
ListMap<String, Uniform> uniforms = shader.getUniformMap(); ListMap<String, Uniform> uniforms = shader.getUniformMap();
// for (Uniform uniform : shader.getUniforms()){
for (int i = 0; i < uniforms.size(); i++) { for (int i = 0; i < uniforms.size(); i++) {
Uniform uniform = uniforms.getValue(i); Uniform uniform = uniforms.getValue(i);
uniform.reset(); // e.g check location again uniform.reset(); // e.g check location again
@ -927,10 +928,10 @@ public class LwjglRenderer implements Renderer {
} }
} }
public void updateShaderSourceData(ShaderSource source, String language) { public void updateShaderSourceData(ShaderSource source) {
int id = source.getId(); int id = source.getId();
if (id == -1) { if (id == -1) {
// create id // Create id
id = glCreateShader(convertShaderType(source.getType())); id = glCreateShader(convertShaderType(source.getType()));
if (id <= 0) { if (id <= 0) {
throw new RendererException("Invalid ID received when trying to create shader."); throw new RendererException("Invalid ID received when trying to create shader.");
@ -941,9 +942,9 @@ public class LwjglRenderer implements Renderer {
throw new RendererException("Cannot recompile shader source"); throw new RendererException("Cannot recompile shader source");
} }
// upload shader source // Upload shader source.
// merge the defines and source code // Merge the defines and source code.
String language = source.getLanguage();
stringBuf.setLength(0); stringBuf.setLength(0);
if (language.startsWith("GLSL")) { if (language.startsWith("GLSL")) {
int version = Integer.parseInt(language.substring(4)); int version = Integer.parseInt(language.substring(4));
@ -999,6 +1000,7 @@ public class LwjglRenderer implements Renderer {
} else { } else {
logger.log(Level.FINE, "{0} compile success", source.getName()); logger.log(Level.FINE, "{0} compile success", source.getName());
} }
source.clearUpdateNeeded();
} else { } else {
logger.log(Level.WARNING, "Bad compile of:\n{0}", logger.log(Level.WARNING, "Bad compile of:\n{0}",
new Object[]{ShaderDebug.formatShaderSource(source.getDefines(), source.getSource(), stringBuf.toString())}); new Object[]{ShaderDebug.formatShaderSource(source.getDefines(), source.getSource(), stringBuf.toString())});
@ -1008,21 +1010,6 @@ public class LwjglRenderer implements Renderer {
throw new RendererException("compile error in:" + source + " error: <not provided>"); throw new RendererException("compile error in:" + source + " error: <not provided>");
} }
} }
source.clearUpdateNeeded();
// only usable if compiled
source.setUsable(compiledOK);
if (!compiledOK) {
// make sure to dispose id cause all program's
// shaders will be cleared later.
glDeleteShader(id);
} else {
// register for cleanup since the ID is usable
// NOTE: From now on cleanup is handled
// by the parent shader object so no need
// to register.
//objManager.registerForCleanup(source);
}
} }
public void updateShaderData(Shader shader) { public void updateShaderData(Shader shader) {
@ -1041,15 +1028,7 @@ public class LwjglRenderer implements Renderer {
for (ShaderSource source : shader.getSources()) { for (ShaderSource source : shader.getSources()) {
if (source.isUpdateNeeded()) { if (source.isUpdateNeeded()) {
updateShaderSourceData(source, shader.getLanguage()); updateShaderSourceData(source);
// shader has been compiled here
}
if (!source.isUsable()) {
// it's useless.. just forget about everything..
shader.setUsable(false);
shader.clearUpdateNeeded();
return;
} }
glAttachShader(id, source.getId()); glAttachShader(id, source.getId());
} }
@ -1057,13 +1036,16 @@ public class LwjglRenderer implements Renderer {
if (caps.contains(Caps.OpenGL30)) { if (caps.contains(Caps.OpenGL30)) {
// Check if GLSL version is 1.5 for shader // Check if GLSL version is 1.5 for shader
GL30.glBindFragDataLocation(id, 0, "outFragColor"); GL30.glBindFragDataLocation(id, 0, "outFragColor");
// For MRT
for(int i = 0 ; i < maxMRTFBOAttachs ; i++) { for(int i = 0 ; i < maxMRTFBOAttachs ; i++) {
GL30.glBindFragDataLocation(id, i, "outFragData[" + i + "]"); GL30.glBindFragDataLocation(id, i, "outFragData[" + i + "]");
} }
} }
// link shaders to program // Link shaders to program
glLinkProgram(id); glLinkProgram(id);
// Check link status
glGetProgram(id, GL_LINK_STATUS, intBuf1); glGetProgram(id, GL_LINK_STATUS, intBuf1);
boolean linkOK = intBuf1.get(0) == GL_TRUE; boolean linkOK = intBuf1.get(0) == GL_TRUE;
String infoLog = null; String infoLog = null;
@ -1089,53 +1071,35 @@ public class LwjglRenderer implements Renderer {
} else { } else {
logger.fine("shader link success"); logger.fine("shader link success");
} }
} else { shader.clearUpdateNeeded();
if (infoLog != null) {
throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
} else {
throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
}
}
shader.clearUpdateNeeded();
if (!linkOK) {
// failure.. forget about everything
shader.resetSources();
shader.setUsable(false);
deleteShader(shader);
} else {
shader.setUsable(true);
if (needRegister) { if (needRegister) {
// Register shader for clean up if it was created in this method.
objManager.registerForCleanup(shader); objManager.registerForCleanup(shader);
statistics.onNewShader(); statistics.onNewShader();
} else { } else {
// OpenGL spec: uniform locations may change after re-link // OpenGL spec: uniform locations may change after re-link
resetUniformLocations(shader); resetUniformLocations(shader);
} }
} else {
if (infoLog != null) {
throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
} else {
throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
}
} }
} }
public void setShader(Shader shader) { public void setShader(Shader shader) {
if (shader == null) { if (shader == null) {
throw new IllegalArgumentException("shader cannot be null"); throw new IllegalArgumentException("Shader cannot be null");
// if (context.boundShaderProgram > 0) {
// glUseProgram(0);
// statistics.onShaderUse(null, true);
// context.boundShaderProgram = 0;
// boundShader = null;
// }
} else { } else {
if (shader.isUpdateNeeded()) { if (shader.isUpdateNeeded()) {
updateShaderData(shader); updateShaderData(shader);
} }
// NOTE: might want to check if any of the // NOTE: might want to check if any of the
// sources need an update? // sources need an update?
if (!shader.isUsable()) {
return;
}
assert shader.getId() > 0; assert shader.getId() > 0;
updateShaderUniforms(shader); updateShaderUniforms(shader);
@ -1148,7 +1112,6 @@ public class LwjglRenderer implements Renderer {
logger.warning("Shader source is not uploaded to GPU, cannot delete."); logger.warning("Shader source is not uploaded to GPU, cannot delete.");
return; return;
} }
source.setUsable(false);
source.clearUpdateNeeded(); source.clearUpdateNeeded();
glDeleteShader(source.getId()); glDeleteShader(source.getId());
source.resetObject(); source.resetObject();
@ -1167,12 +1130,9 @@ public class LwjglRenderer implements Renderer {
} }
} }
// kill all references so sources can be collected
// if needed.
shader.resetSources();
glDeleteProgram(shader.getId()); glDeleteProgram(shader.getId());
statistics.onDeleteShader(); statistics.onDeleteShader();
shader.resetObject();
} }
/*********************************************************************\ /*********************************************************************\
@ -2116,46 +2076,6 @@ public class LwjglRenderer implements Renderer {
throw new UnsupportedOperationException("Unknown buffer format."); throw new UnsupportedOperationException("Unknown buffer format.");
} }
} }
// }else{
// if (created || vb.hasDataSizeChanged()){
// glBufferData(target, vb.getData().capacity() * vb.getFormat().getComponentSize(), usage);
// }
//
// ByteBuffer buf = glMapBuffer(target,
// GL_WRITE_ONLY,
// vb.getMappedData());
//
// if (buf != vb.getMappedData()){
// buf = buf.order(ByteOrder.nativeOrder());
// vb.setMappedData(buf);
// }
//
// buf.clear();
//
// switch (vb.getFormat()){
// case Byte:
// case UnsignedByte:
// buf.put( (ByteBuffer) vb.getData() );
// break;
// case Short:
// case UnsignedShort:
// buf.asShortBuffer().put( (ShortBuffer) vb.getData() );
// break;
// case Int:
// case UnsignedInt:
// buf.asIntBuffer().put( (IntBuffer) vb.getData() );
// break;
// case Float:
// buf.asFloatBuffer().put( (FloatBuffer) vb.getData() );
// break;
// case Double:
// break;
// default:
// throw new RuntimeException("Unknown buffer format.");
// }
//
// glUnmapBuffer(target);
// }
vb.clearUpdateNeeded(); vb.clearUpdateNeeded();
} }

Loading…
Cancel
Save