Adds a few missing features into the shader-based renderer relying on JOGL 2.0

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9886 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
jul..om 12 years ago
parent f75b45aff7
commit 80f94431d9
  1. 375
      engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java

@ -36,6 +36,10 @@ import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
import com.jme3.renderer.Caps; import com.jme3.renderer.Caps;
import com.jme3.renderer.IDList; import com.jme3.renderer.IDList;
import com.jme3.renderer.RenderContext; import com.jme3.renderer.RenderContext;
@ -49,6 +53,7 @@ import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage; import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.shader.Shader; import com.jme3.shader.Shader;
import com.jme3.shader.Shader.ShaderSource; import com.jme3.shader.Shader.ShaderSource;
import com.jme3.shader.Uniform;
import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer;
import com.jme3.texture.FrameBuffer.RenderBuffer; import com.jme3.texture.FrameBuffer.RenderBuffer;
import com.jme3.texture.Image; import com.jme3.texture.Image;
@ -57,6 +62,7 @@ import com.jme3.texture.Texture.WrapAxis;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
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.NativeObjectManager; import com.jme3.util.NativeObjectManager;
import java.nio.Buffer; import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -71,6 +77,7 @@ import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES1; import javax.media.opengl.GL2ES1;
import javax.media.opengl.GL2ES2; import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3; import javax.media.opengl.GL2GL3;
import javax.media.opengl.GL3;
import javax.media.opengl.GLContext; import javax.media.opengl.GLContext;
import javax.media.opengl.fixedfunc.GLLightingFunc; import javax.media.opengl.fixedfunc.GLLightingFunc;
import javax.media.opengl.fixedfunc.GLMatrixFunc; import javax.media.opengl.fixedfunc.GLMatrixFunc;
@ -81,8 +88,8 @@ public class JoglRenderer implements Renderer {
private static final Logger logger = Logger.getLogger(JoglRenderer.class.getName()); private static final Logger logger = Logger.getLogger(JoglRenderer.class.getName());
private static final boolean VALIDATE_SHADER = false; private static final boolean VALIDATE_SHADER = false;
private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); //private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
private final StringBuilder stringBuf = new StringBuilder(250); //private final StringBuilder stringBuf = new StringBuilder(250);
private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1);
private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16); private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16);
private RenderContext context = new RenderContext(); private RenderContext context = new RenderContext();
@ -121,7 +128,7 @@ public class JoglRenderer implements Renderer {
public JoglRenderer() { public JoglRenderer() {
} }
protected void updateNameBuffer() { /*protected void updateNameBuffer() {
int len = stringBuf.length(); int len = stringBuf.length();
nameBuf.position(0); nameBuf.position(0);
@ -131,12 +138,16 @@ public class JoglRenderer implements Renderer {
} }
nameBuf.rewind(); nameBuf.rewind();
} }*/
public Statistics getStatistics() { public Statistics getStatistics() {
return statistics; return statistics;
} }
public EnumSet<Caps> getCaps() {
return caps;
}
public void initialize() { public void initialize() {
GL gl = GLContext.getCurrentGL(); GL gl = GLContext.getCurrentGL();
//logger.log(Level.INFO, "Vendor: {0}", gl.glGetString(GL.GL_VENDOR)); //logger.log(Level.INFO, "Vendor: {0}", gl.glGetString(GL.GL_VENDOR));
@ -396,30 +407,20 @@ public class JoglRenderer implements Renderer {
} }
caps.add(Caps.Multisample); caps.add(Caps.Multisample);
} }
}
public EnumSet<Caps> getCaps() {
return caps;
}
public void setBackgroundColor(ColorRGBA color) { logger.log(Level.INFO, "Caps: {0}", caps);
GL gl = GLContext.getCurrentGL();
gl.glClearColor(color.r, color.g, color.b, color.a);
} }
public void setAlphaToCoverage(boolean value) { public void invalidateState() {
if (caps.contains(Caps.Multisample)) { context.reset();
GL gl = GLContext.getCurrentGL(); boundShader = null;
if (value) { lastFb = null;
gl.glEnable(GL2.GL_SAMPLE_ALPHA_TO_COVERAGE);
} else {
gl.glDisable(GL2.GL_SAMPLE_ALPHA_TO_COVERAGE);
}
}
}
public void cleanup() { GL gl = GLContext.getCurrentGL();
objManager.deleteAllObjects(this); gl.glGetIntegerv(GL2.GL_DRAW_BUFFER, intBuf16);
initialDrawBuf = intBuf16.get(0);
gl.glGetIntegerv(GL2.GL_READ_BUFFER, intBuf16);
initialReadBuf = intBuf16.get(0);
} }
public void resetGLObjects() { public void resetGLObjects() {
@ -430,6 +431,18 @@ public class JoglRenderer implements Renderer {
context.reset(); context.reset();
} }
public void cleanup() {
objManager.deleteAllObjects(this);
}
/*********************************************************************\
|* Render State *|
\*********************************************************************/
public void setDepthRange(float start, float end) {
GL gl = GLContext.getCurrentGL();
gl.glDepthRange(start, end);
}
public void clearBuffers(boolean color, boolean depth, boolean stencil) { public void clearBuffers(boolean color, boolean depth, boolean stencil) {
GL gl = GLContext.getCurrentGL(); GL gl = GLContext.getCurrentGL();
int bits = 0; int bits = 0;
@ -447,7 +460,24 @@ public class JoglRenderer implements Renderer {
} }
} }
public void setBackgroundColor(ColorRGBA color) {
GL gl = GLContext.getCurrentGL();
gl.glClearColor(color.r, color.g, color.b, color.a);
}
public void setAlphaToCoverage(boolean value) {
if (caps.contains(Caps.Multisample)) {
GL gl = GLContext.getCurrentGL();
if (value) {
gl.glEnable(GL2.GL_SAMPLE_ALPHA_TO_COVERAGE);
} else {
gl.glDisable(GL2.GL_SAMPLE_ALPHA_TO_COVERAGE);
}
}
}
public void applyRenderState(RenderState state) { public void applyRenderState(RenderState state) {
//FIXME implement missing features
GL gl = GLContext.getCurrentGL(); GL gl = GLContext.getCurrentGL();
if (state.isWireframe() && !context.wireframe) { if (state.isWireframe() && !context.wireframe) {
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE); gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
@ -576,15 +606,55 @@ public class JoglRenderer implements Renderer {
} }
} }
public void onFrame() { private int convertStencilOperation(RenderState.StencilOperation stencilOp) {
objManager.deleteUnused(this); switch (stencilOp) {
case Keep:
return GL.GL_KEEP;
case Zero:
return GL.GL_ZERO;
case Replace:
return GL.GL_REPLACE;
case Increment:
return GL.GL_INCR;
case IncrementWrap:
return GL.GL_INCR_WRAP;
case Decrement:
return GL.GL_DECR;
case DecrementWrap:
return GL.GL_DECR_WRAP;
case Invert:
return GL.GL_INVERT;
default:
throw new UnsupportedOperationException("Unrecognized stencil operation: " + stencilOp);
}
} }
public void setDepthRange(float start, float end) { private int convertTestFunction(RenderState.TestFunction testFunc) {
GL gl = GLContext.getCurrentGL(); switch (testFunc) {
gl.glDepthRange(start, end); case Never:
return GL.GL_NEVER;
case Less:
return GL.GL_LESS;
case LessOrEqual:
return GL.GL_LEQUAL;
case Greater:
return GL.GL_GREATER;
case GreaterOrEqual:
return GL.GL_GEQUAL;
case Equal:
return GL.GL_EQUAL;
case NotEqual:
return GL.GL_NOTEQUAL;
case Always:
return GL.GL_ALWAYS;
default:
throw new UnsupportedOperationException("Unrecognized test function: " + testFunc);
}
} }
/*********************************************************************\
|* Camera and World transforms *|
\*********************************************************************/
public void setViewPort(int x, int y, int width, int height) { public void setViewPort(int x, int y, int width, int height) {
GL gl = GLContext.getCurrentGL(); GL gl = GLContext.getCurrentGL();
gl.glViewport(x, y, width, height); gl.glViewport(x, y, width, height);
@ -611,104 +681,184 @@ public class JoglRenderer implements Renderer {
} }
} }
private FloatBuffer storeMatrix(Matrix4f matrix, FloatBuffer store) { public void onFrame() {
store.rewind(); objManager.deleteUnused(this);
matrix.fillFloatBuffer(store, true);
store.rewind();
return store;
} }
public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) { public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) {
this.viewMatrix.set(viewMatrix);
this.projMatrix.set(projMatrix);
GL gl = GLContext.getCurrentGL();
if (context.matrixMode != GLMatrixFunc.GL_PROJECTION) {
gl.getGL2().glMatrixMode(GLMatrixFunc.GL_PROJECTION);
context.matrixMode = GLMatrixFunc.GL_PROJECTION;
}
gl.getGL2().glLoadMatrixf(storeMatrix(projMatrix, fb16));
} }
public void setWorldMatrix(Matrix4f worldMatrix) { public void setWorldMatrix(Matrix4f worldMatrix) {
this.worldMatrix.set(worldMatrix); }
/*********************************************************************\
|* Shaders *|
\*********************************************************************/
protected void updateUniformLocation(Shader shader, Uniform uniform) {
//stringBuf.setLength(0);
//stringBuf.append(uniform.getName()).append('\0');
//updateNameBuffer();
GL gl = GLContext.getCurrentGL(); GL gl = GLContext.getCurrentGL();
if (context.matrixMode != GLMatrixFunc.GL_MODELVIEW) { int loc = gl.getGL2().glGetUniformLocation(shader.getId(), uniform.getName());
gl.getGL2().glMatrixMode(GLMatrixFunc.GL_MODELVIEW); if (loc < 0) {
context.matrixMode = GLMatrixFunc.GL_MODELVIEW; uniform.setLocation(-1);
// uniform is not declared in shader
logger.log(Level.INFO, "Uniform {0} is not declared in shader {1}.", new Object[]{uniform.getName(), shader.getSources()});
} else {
uniform.setLocation(loc);
} }
gl.getGL2().glLoadMatrixf(storeMatrix(viewMatrix, fb16));
gl.getGL2().glMultMatrixf(storeMatrix(worldMatrix, fb16));
} }
public void setLighting(LightList list) { protected void bindProgram(Shader shader) {
/*GL gl = GLContext.getCurrentGL(); int shaderId = shader.getId();
if (list == null || list.size() == 0) { if (context.boundShaderProgram != shaderId) {
// turn off lighting GL gl = GLContext.getCurrentGL();
gl.glDisable(GLLightingFunc.GL_LIGHTING); gl.getGL2().glUseProgram(shaderId);
return; statistics.onShaderUse(shader, true);
} boundShader = shader;
context.boundShaderProgram = shaderId;
} else {
statistics.onShaderUse(shader, false);
}
}
gl.glEnable(GLLightingFunc.GL_LIGHTING); protected void updateUniform(Shader shader, Uniform uniform) {
gl.getGL2().glShadeModel(GLLightingFunc.GL_SMOOTH); int shaderId = shader.getId();
float[] temp = new float[4]; assert uniform.getName() != null;
assert shaderId > 0;
// reset model view to specify bindProgram(shader);
// light positions in world space
// instead of model space
// gl.glPushMatrix();
// gl.glLoadIdentity();
for (int i = 0; i < list.size() + 1; i++) { int loc = uniform.getLocation();
if (loc == -1) {
return;
}
int lightId = GLLightingFunc.GL_LIGHT0 + i; if (loc == -2) {
// get uniform location
updateUniformLocation(shader, uniform);
if (uniform.getLocation() == -1) {
// not declared, ignore
uniform.clearUpdateNeeded();
return;
}
loc = uniform.getLocation();
}
if (list.size() <= i) { if (uniform.getVarType() == null) {
// goes beyond the num lights we need return; // value not set yet..
// disable it }
gl.glDisable(lightId); statistics.onUniformSet();
break;
}
Light l = list.get(i); uniform.clearUpdateNeeded();
FloatBuffer fb;
GL gl = GLContext.getCurrentGL();
switch (uniform.getVarType()) {
case Float:
Float f = (Float) uniform.getValue();
gl.getGL2().glUniform1f(loc, f.floatValue());
break;
case Vector2:
Vector2f v2 = (Vector2f) uniform.getValue();
gl.getGL2().glUniform2f(loc, v2.getX(), v2.getY());
break;
case Vector3:
Vector3f v3 = (Vector3f) uniform.getValue();
gl.getGL2().glUniform3f(loc, v3.getX(), v3.getY(), v3.getZ());
break;
case Vector4:
Object val = uniform.getValue();
if (val instanceof ColorRGBA) {
ColorRGBA c = (ColorRGBA) val;
gl.getGL2().glUniform4f(loc, c.r, c.g, c.b, c.a);
} else if (val instanceof Vector4f) {
Vector4f c = (Vector4f) val;
gl.getGL2().glUniform4f(loc, c.x, c.y, c.z, c.w);
} else {
Quaternion c = (Quaternion) uniform.getValue();
gl.getGL2().glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW());
}
break;
case Boolean:
Boolean b = (Boolean) uniform.getValue();
gl.getGL2().glUniform1i(loc, b.booleanValue() ? GL.GL_TRUE : GL.GL_FALSE);
break;
case Matrix3:
fb = (FloatBuffer) uniform.getValue();
assert fb.remaining() == 9;
gl.getGL2().glUniformMatrix3fv(loc, 1, false, fb);
break;
case Matrix4:
fb = (FloatBuffer) uniform.getValue();
assert fb.remaining() == 16;
gl.getGL2().glUniformMatrix4fv(loc, 1, false, fb);
break;
case FloatArray:
fb = (FloatBuffer) uniform.getValue();
gl.getGL2().glUniform1fv(loc, fb.remaining(), fb);
break;
case Vector2Array:
fb = (FloatBuffer) uniform.getValue();
gl.getGL2().glUniform2fv(loc, fb.remaining(), fb);
break;
case Vector3Array:
fb = (FloatBuffer) uniform.getValue();
gl.getGL2().glUniform3fv(loc, fb.remaining(), fb);
break;
case Vector4Array:
fb = (FloatBuffer) uniform.getValue();
gl.getGL2().glUniform4fv(loc, fb.remaining(), fb);
break;
case Matrix4Array:
fb = (FloatBuffer) uniform.getValue();
gl.getGL2().glUniformMatrix4fv(loc, 1, false, fb);
break;
case Int:
Integer i = (Integer) uniform.getValue();
gl.getGL2().glUniform1i(loc, i.intValue());
break;
default:
throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType());
}
}
if (!l.isEnabled()) { protected void updateShaderUniforms(Shader shader) {
gl.glDisable(lightId); ListMap<String, Uniform> uniforms = shader.getUniformMap();
continue; for (int i = 0; i < uniforms.size(); i++) {
} Uniform uniform = uniforms.getValue(i);
if (uniform.isUpdateNeeded()) {
updateUniform(shader, uniform);
}
}
}
ColorRGBA color = l.getColor(); protected void resetUniformLocations(Shader shader) {
color.toArray(temp); ListMap<String, Uniform> uniforms = shader.getUniformMap();
for (int i = 0; i < uniforms.size(); i++) {
gl.glEnable(lightId); Uniform uniform = uniforms.getValue(i);
gl.getGL2().glLightfv(lightId, GLLightingFunc.GL_DIFFUSE, temp, 0); uniform.reset(); // e.g check location again
gl.getGL2().glLightfv(lightId, GLLightingFunc.GL_SPECULAR, temp, 0); }
}
ColorRGBA.Black.toArray(temp);
gl.getGL2().glLightfv(lightId, GLLightingFunc.GL_AMBIENT, temp, 0);
switch (l.getType()) {
case Directional:
DirectionalLight dl = (DirectionalLight) l;
dl.getDirection().toArray(temp);
temp[3] = 0f; // marks to GL its a directional light
gl.getGL2().glLightfv(lightId, GLLightingFunc.GL_POSITION, temp, 0);
break;
case Point:
PointLight pl = (PointLight) l;
pl.getPosition().toArray(temp);
temp[3] = 1f; // marks to GL its a point light
gl.getGL2().glLightfv(lightId, GLLightingFunc.GL_POSITION, temp, 0);
break;
}
} /*
* (Non-javadoc)
* Only used for fixed-function. Ignored.
*/
public void setLighting(LightList list) {
}
// restore modelview to original value public int convertShaderType(Shader.ShaderType type) {
// gl.glPopMatrix(); switch (type) {
* */ case Fragment:
return GL2.GL_FRAGMENT_SHADER;
case Vertex:
return GL2.GL_VERTEX_SHADER;
// case Geometry:
// return ARBGeometryShader4.GL_GEOMETRY_SHADER_ARB;
default:
throw new UnsupportedOperationException("Unrecognized shader type.");
}
} }
public void deleteShaderSource(ShaderSource source) { public void deleteShaderSource(ShaderSource source) {
@ -1758,19 +1908,6 @@ public class JoglRenderer implements Renderer {
}*/ }*/
} }
public void invalidateState() {
context.reset();
boundShader = null;
lastFb = null;
GL gl = GLContext.getCurrentGL();
gl.glGetIntegerv(GL2.GL_DRAW_BUFFER, intBuf16);
initialDrawBuf = intBuf16.get(0);
gl.glGetIntegerv(GL2.GL_READ_BUFFER, intBuf16);
initialReadBuf = intBuf16.get(0);
}
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) { public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
GL gl = GLContext.getCurrentGL(); GL gl = GLContext.getCurrentGL();
if (gl.isExtensionAvailable("GL_EXT_framebuffer_blit")) { if (gl.isExtensionAvailable("GL_EXT_framebuffer_blit")) {

Loading…
Cancel
Save