Refactor renderer system

* Support OpenGL ES 2 in GLRenderer (various error fixes)
 * Get rid of OpenGL 1 remenants
 * Other minor cleanups
experimental
shadowislord 10 years ago
parent 69db9989a4
commit 6ca111b13d
  1. 13
      jme3-android/src/main/java/com/jme3/renderer/android/OGLESShaderRenderer.java
  2. 6
      jme3-core/src/main/java/com/jme3/material/Material.java
  3. 37
      jme3-core/src/main/java/com/jme3/renderer/RenderContext.java
  4. 27
      jme3-core/src/main/java/com/jme3/renderer/RenderManager.java
  5. 41
      jme3-core/src/main/java/com/jme3/renderer/Renderer.java
  6. 5
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java
  7. 2
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java
  8. 2
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java
  9. 1
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLFbo.java
  10. 1
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java
  11. 353
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  12. 2
      jme3-core/src/main/java/com/jme3/system/NullRenderer.java
  13. 2
      jme3-ios/src/main/java/com/jme3/renderer/ios/IGLESShaderRenderer.java
  14. 23
      jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java
  15. 2
      jme3-jogl/src/main/java/com/jme3/system/jogl/JoglCanvas.java
  16. 2
      jme3-jogl/src/main/java/com/jme3/system/jogl/JoglDisplay.java
  17. 2
      jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtCanvas.java
  18. 2
      jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java
  19. 2
      jme3-jogl/src/main/java/com/jme3/system/jogl/JoglOffscreenBuffer.java
  20. 6
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
  21. 16
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglRenderer.java
  22. 4
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/TextureUtil.java
  23. 2
      jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java
  24. 2
      jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java

@ -643,18 +643,12 @@ public class OGLESShaderRenderer implements Renderer {
}
}
public void onFrame() {
public void postFrame() {
RendererUtil.checkGLErrorForced();
objManager.deleteUnused(this);
}
public void setWorldMatrix(Matrix4f worldMatrix) {
}
public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) {
}
/*********************************************************************\
|* Shaders *|
\*********************************************************************/
@ -1072,9 +1066,6 @@ public class OGLESShaderRenderer implements Renderer {
/*********************************************************************\
|* Framebuffers *|
\*********************************************************************/
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
copyFrameBuffer(src, dst, true);
}
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
throw new RendererException("Copy framebuffer not implemented yet.");

@ -1199,20 +1199,18 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
// send lighting information, if needed
switch (techDef.getLightMode()) {
case Disable:
r.setLighting(null);
break;
case SinglePass:
int nbRenderedLights = 0;
resetUniformsNotSetByCurrent(shader);
while(nbRenderedLights < lights.size()){
while (nbRenderedLights < lights.size()) {
nbRenderedLights = updateLightListUniforms(shader, geom, lights, rm.getSinglePassLightBatchSize(), rm, nbRenderedLights);
r.setShader(shader);
renderMeshFromGeometry(r, geom);
}
return;
case FixedPipeline:
r.setLighting(lights);
break;
throw new IllegalArgumentException("OpenGL1 is not supported");
case MultiPass:
// NOTE: Special case!
resetUniformsNotSetByCurrent(shader);

@ -250,36 +250,6 @@ public class RenderContext {
*/
public IDList attribIndexList = new IDList();
/**
* Ambient color (GL1 only)
*/
public ColorRGBA ambient;
/**
* Diffuse color (GL1 only)
*/
public ColorRGBA diffuse;
/**
* Specular color (GL1 only)
*/
public ColorRGBA specular;
/**
* Material color (GL1 only)
*/
public ColorRGBA color;
/**
* Shininess (GL1 only)
*/
public float shininess;
/**
* Use vertex color (GL1 only)
*/
public boolean useVertexColor;
/**
* depth tets function
*/
@ -290,10 +260,11 @@ public class RenderContext {
*/
public RenderState.TestFunction alphaFunc = RenderState.TestFunction.Greater;
public int initialDrawBuf;
public int initialReadBuf;
public ColorRGBA clearColor = new ColorRGBA(0,0,0,0);
/**
* Reset the RenderContext to default GL state
*/
@ -343,10 +314,8 @@ public class RenderContext {
frontStencilFunction = RenderState.TestFunction.Always;
backStencilFunction = RenderState.TestFunction.Always;
ambient = diffuse = specular = color = null;
shininess = 0;
useVertexColor = false;
depthFunc = RenderState.TestFunction.LessOrEqual;
alphaFunc = RenderState.TestFunction.Greater;
clearColor.set(0,0,0,0);
}
}

@ -82,7 +82,6 @@ public class RenderManager {
private Material forcedMaterial = null;
private String forcedTechnique = null;
private RenderState forcedRenderState = null;
private boolean shader;
private int viewX, viewY, viewWidth, viewHeight;
private Matrix4f orthoMatrix = new Matrix4f();
private LightList filteredLightList = new LightList(null);
@ -476,11 +475,7 @@ public class RenderManager {
* @param mat The world matrix to set
*/
public void setWorldMatrix(Matrix4f mat) {
if (shader) {
uniformBindingManager.setWorldMatrix(mat);
} else {
renderer.setWorldMatrix(mat);
}
uniformBindingManager.setWorldMatrix(mat);
}
/**
@ -927,19 +922,10 @@ public class RenderManager {
}
private void setViewProjection(Camera cam, boolean ortho) {
if (shader) {
if (ortho) {
uniformBindingManager.setCamera(cam, Matrix4f.IDENTITY, orthoMatrix, orthoMatrix);
} else {
uniformBindingManager.setCamera(cam, cam.getViewMatrix(), cam.getProjectionMatrix(), cam.getViewProjectionMatrix());
}
if (ortho) {
uniformBindingManager.setCamera(cam, Matrix4f.IDENTITY, orthoMatrix, orthoMatrix);
} else {
if (ortho) {
renderer.setViewProjectionMatrices(Matrix4f.IDENTITY, orthoMatrix);
} else {
renderer.setViewProjectionMatrices(cam.getViewMatrix(),
cam.getProjectionMatrix());
}
uniformBindingManager.setCamera(cam, cam.getViewMatrix(), cam.getProjectionMatrix(), cam.getViewProjectionMatrix());
}
}
@ -1087,10 +1073,6 @@ public class RenderManager {
if (prof!=null) prof.vpStep(VpStep.EndRender, vp, null);
}
public void setUsingShaders(boolean usingShaders) {
this.shader = usingShaders;
}
/**
* Called by the application to render any ViewPorts
@ -1110,7 +1092,6 @@ public class RenderManager {
return;
}
this.shader = renderer.getCaps().contains(Caps.GLSL100);
uniformBindingManager.newFrame();
if (prof!=null) prof.appStep(AppStep.RenderPreviewViewPorts);

@ -31,10 +31,8 @@
*/
package com.jme3.renderer;
import com.jme3.light.LightList;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix4f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.shader.Shader;
@ -55,6 +53,11 @@ import java.util.EnumSet;
*/
public interface Renderer {
/**
* Detects available capabilities of the GPU.
*
* Must be called prior to any other Renderer methods.
*/
public void initialize();
/**
@ -113,24 +116,7 @@ public interface Renderer {
/**
* Called when a new frame has been rendered.
*/
public void onFrame();
/**
* Set the world matrix to use. Does nothing if the Renderer is
* shader based.
*
* @param worldMatrix World matrix to use.
*/
public void setWorldMatrix(Matrix4f worldMatrix);
/**
* Sets the view and projection matrices to use. Does nothing if the Renderer
* is shader based.
*
* @param viewMatrix The view matrix to use.
* @param projMatrix The projection matrix to use.
*/
public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix);
public void postFrame();
/**
* Set the viewport location and resolution on the screen.
@ -160,16 +146,6 @@ public interface Renderer {
*/
public void clearClipRect();
/**
* Set lighting state.
* Does nothing if the renderer is shader based.
* The lights should be provided in world space.
* Specify <code>null</code> to disable lighting.
*
* @param lights The light list to set.
*/
public void setLighting(LightList lights);
/**
* Sets the shader to use for rendering.
* If the shader has not been uploaded yet, it is compiled
@ -195,11 +171,6 @@ public interface Renderer {
*/
public void deleteShaderSource(ShaderSource source);
/**
* Copies contents from src to dst, scaling if necessary.
*/
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst);
/**
* Copies contents from src to dst, scaling if necessary.
* set copyDepth to false to only copy the color buffers.

@ -79,6 +79,9 @@ public interface GL {
public static final int GL_INCR_WRAP = 0x8507;
public static final int GL_INFO_LOG_LENGTH = 0x8B84;
public static final int GL_INT = 0x1404;
public static final int GL_INVALID_ENUM = 0x500;
public static final int GL_INVALID_VALUE = 0x501;
public static final int GL_INVALID_OPERATION = 0x502;
public static final int GL_INVERT = 0x150A;
public static final int GL_KEEP = 0x1E00;
public static final int GL_LEQUAL = 0x203;
@ -102,12 +105,14 @@ public interface GL {
public static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702;
public static final int GL_NEAREST_MIPMAP_NEAREST = 0x2700;
public static final int GL_NEVER = 0x200;
public static final int GL_NO_ERROR = 0x0;
public static final int GL_NONE = 0x0;
public static final int GL_NOTEQUAL = 0x205;
public static final int GL_ONE = 0x1;
public static final int GL_ONE_MINUS_DST_COLOR = 0x307;
public static final int GL_ONE_MINUS_SRC_ALPHA = 0x303;
public static final int GL_ONE_MINUS_SRC_COLOR = 0x301;
public static final int GL_OUT_OF_MEMORY = 0x505;
public static final int GL_POINTS = 0x0;
public static final int GL_POLYGON_OFFSET_FILL = 0x8037;
public static final int GL_REPEAT = 0x2901;

@ -62,6 +62,8 @@ public interface GL2 extends GL {
public static final int GL_MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A;
public static final int GL_READ_BUFFER = 0xC02;
public static final int GL_RGB8 = 0x8051;
public static final int GL_STACK_OVERFLOW = 0x503;
public static final int GL_STACK_UNDERFLOW = 0x504;
public static final int GL_TEXTURE_3D = 0x806F;
public static final int GL_POINT_SPRITE = 0x8861;
public static final int GL_TEXTURE_COMPARE_FUNC = 0x884D;

@ -43,7 +43,6 @@ import java.nio.IntBuffer;
*/
public interface GLExt extends GLFbo {
public static final int GL_ETC1_RGB8_OES = 0x8D64;
public static final int GL_COMPRESSED_RGB8_ETC2 = 0x9274;
public static final int GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
public static final int GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
@ -56,6 +55,7 @@ public interface GLExt extends GLFbo {
public static final int GL_DEPTH_COMPONENT32F = 0x8CAC;
public static final int GL_DEPTH24_STENCIL8_EXT = 0x88F0;
public static final int GL_DEPTH_STENCIL_EXT = 0x84F9;
public static final int GL_ETC1_RGB8_OES = 0x8D64;
public static final int GL_FRAMEBUFFER_SRGB_CAPABLE_EXT = 0x8DBA;
public static final int GL_FRAMEBUFFER_SRGB_EXT = 0x8DB9;
public static final int GL_HALF_FLOAT_ARB = 0x140B;

@ -60,6 +60,7 @@ public interface GLFbo {
public static final int GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT = 0x8D56;
public static final int GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT = 0x8CDC;
public static final int GL_FRAMEBUFFER_UNSUPPORTED_EXT = 0x8CDD;
public static final int GL_INVALID_FRAMEBUFFER_OPERATION_EXT = 0x506;
public static final int GL_MAX_COLOR_ATTACHMENTS_EXT = 0x8CDF;
public static final int GL_MAX_RENDERBUFFER_SIZE_EXT = 0x84E8;
public static final int GL_READ_FRAMEBUFFER_BINDING_EXT = 0x8CAA;

@ -126,6 +126,7 @@ public final class GLImageFormats {
format(formatToGL, Format.RGB8, GLExt.GL_RGBA8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.RGBA8, GLExt.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
} else {
// Actually, the internal format isn't used for OpenGL ES 2! This is the same as the above..
format(formatToGL, Format.Alpha8, GL.GL_RGBA4, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8, GL.GL_RGB565, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GL.GL_RGBA4, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE);

@ -70,6 +70,8 @@ public class GLRenderer implements Renderer {
private static final Logger logger = Logger.getLogger(GLRenderer.class.getName());
private static final boolean VALIDATE_SHADER = false;
private static final Pattern GLVERSION_PATTERN = Pattern.compile(".*?(\\d+)\\.(\\d+).*");
private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
private final StringBuilder stringBuf = new StringBuilder(250);
private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1);
@ -117,18 +119,6 @@ public class GLRenderer implements Renderer {
this.texUtil = new TextureUtil(gl, gl2, glext);
}
protected void updateNameBuffer() {
int len = stringBuf.length();
nameBuf.position(0);
nameBuf.limit(len);
for (int i = 0; i < len; i++) {
nameBuf.put((byte) stringBuf.charAt(i));
}
nameBuf.rewind();
}
@Override
public Statistics getStatistics() {
return statistics;
@ -147,12 +137,8 @@ public class GLRenderer implements Renderer {
return extensionSet;
}
private static final Pattern VERSION = Pattern.compile(".*?(\\d+)\\.(\\d+).*");
public static int extractVersion(String version) {
Matcher m = VERSION.matcher(version);
Matcher m = GLVERSION_PATTERN.matcher(version);
if (m.matches()) {
int major = Integer.parseInt(m.group(1));
int minor = Integer.parseInt(m.group(2));
@ -492,12 +478,6 @@ public class GLRenderer implements Renderer {
invalidateState();
}
private void checkCap(Caps cap) {
if (!caps.contains(cap)) {
throw new UnsupportedOperationException("Required capability missing: " + cap.name());
}
}
/*********************************************************************\
|* Render State *|
\*********************************************************************/
@ -516,11 +496,10 @@ public class GLRenderer implements Renderer {
bits = GL.GL_COLOR_BUFFER_BIT;
}
if (depth) {
//glClear(GL.GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false
//here s some link on openl board
//http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223
//if depth clear is requested, we enable the depthMask
// glClear(GL.GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false
// here s some link on openl board
// http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223
// if depth clear is requested, we enable the depthMask
if (context.depthWriteEnabled == false) {
gl.glDepthMask(true);
context.depthWriteEnabled = true;
@ -528,6 +507,8 @@ public class GLRenderer implements Renderer {
bits |= GL.GL_DEPTH_BUFFER_BIT;
}
if (stencil) {
// May need to set glStencilMask(0xFF) here if we ever allow users
// to change the stencil mask.
bits |= GL.GL_STENCIL_BUFFER_BIT;
}
if (bits != 0) {
@ -536,7 +517,10 @@ public class GLRenderer implements Renderer {
}
public void setBackgroundColor(ColorRGBA color) {
gl.glClearColor(color.r, color.g, color.b, color.a);
if (!context.clearColor.equals(color)) {
gl.glClearColor(color.r, color.g, color.b, color.a);
context.clearColor.set(color);
}
}
public void setAlphaToCoverage(boolean value) {
@ -608,30 +592,28 @@ public class GLRenderer implements Renderer {
context.colorWriteEnabled = false;
}
if (state.isPointSprite() && !context.pointSprite) {
// Only enable/disable sprite
if (context.boundTextures[0] != null) {
if (context.boundTextureUnit != 0) {
gl.glActiveTexture(GL.GL_TEXTURE0);
context.boundTextureUnit = 0;
}
if (gl2 != null) {
if (gl2 != null) {
if (state.isPointSprite() && !context.pointSprite) {
// Only enable/disable sprite
if (context.boundTextures[0] != null) {
if (context.boundTextureUnit != 0) {
gl.glActiveTexture(GL.GL_TEXTURE0);
context.boundTextureUnit = 0;
}
gl2.glEnable(GL2.GL_POINT_SPRITE);
gl2.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
}
}
context.pointSprite = true;
} else if (!state.isPointSprite() && context.pointSprite) {
if (context.boundTextures[0] != null) {
if (context.boundTextureUnit != 0) {
gl.glActiveTexture(GL.GL_TEXTURE0);
context.boundTextureUnit = 0;
}
if (gl2 != null) {
context.pointSprite = true;
} else if (!state.isPointSprite() && context.pointSprite) {
if (context.boundTextures[0] != null) {
if (context.boundTextureUnit != 0) {
gl.glActiveTexture(GL.GL_TEXTURE0);
context.boundTextureUnit = 0;
}
gl2.glDisable(GL2.GL_POINT_SPRITE);
gl2.glDisable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
context.pointSprite = false;
}
context.pointSprite = false;
}
}
@ -858,24 +840,15 @@ public class GLRenderer implements Renderer {
}
}
public void onFrame() {
public void postFrame() {
objManager.deleteUnused(this);
// statistics.clearFrame();
}
public void setWorldMatrix(Matrix4f worldMatrix) {
}
public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) {
}
/*********************************************************************\
|* Shaders *|
\*********************************************************************/
protected void updateUniformLocation(Shader shader, Uniform uniform) {
stringBuf.setLength(0);
stringBuf.append(uniform.getName()).append('\0');
int loc = gl.glGetUniformLocation(shader.getId(), stringBuf.toString());
int loc = gl.glGetUniformLocation(shader.getId(), uniform.getName());
if (loc < 0) {
uniform.setLocation(-1);
// uniform is not declared in shader
@ -1020,13 +993,6 @@ public class GLRenderer implements Renderer {
}
}
/*
* (Non-javadoc)
* Only used for fixed-function. Ignored.
*/
public void setLighting(LightList list) {
}
public int convertShaderType(ShaderType type) {
switch (type) {
case Fragment:
@ -1052,9 +1018,16 @@ public class GLRenderer implements Renderer {
throw new RendererException("Cannot recompile shader source");
}
boolean gles2 = caps.contains(Caps.OpenGLES20);
String language = source.getLanguage();
if (gles2 && !language.equals("GLSL100")) {
throw new RendererException("This shader cannot run in OpenGL ES 2. "
+ "Only GLSL 1.00 shaders are supported.");
}
// Upload shader source.
// Merge the defines and source code.
String language = source.getLanguage();
stringBuf.setLength(0);
if (language.startsWith("GLSL")) {
int version = Integer.parseInt(language.substring(4));
@ -1066,11 +1039,20 @@ public class GLRenderer implements Renderer {
}
stringBuf.append("\n");
} else {
// version 100 does not exist in desktop GLSL.
// put version 110 in that case to enable strict checking
stringBuf.append("#version 110\n");
if (gles2) {
if (source.getType() == ShaderType.Fragment) {
// GLES2 requires precision qualifier.
stringBuf.append("precision mediump float;\n");
}
} else {
// version 100 does not exist in desktop GLSL.
// put version 110 in that case to enable strict checking
// (Only enabled for desktop GL)
stringBuf.append("#version 110\n");
}
}
}
stringBuf.append(source.getDefines());
stringBuf.append(source.getSource());
@ -1309,8 +1291,7 @@ public class GLRenderer implements Renderer {
throw ex;
}
} else {
throw new RendererException("EXT_framebuffer_blit required.");
// TODO: support non-blit copies?
throw new RendererException("Framebuffer blitting not supported by the video hardware");
}
}
@ -1504,10 +1485,10 @@ public class GLRenderer implements Renderer {
}
if (!caps.contains(Caps.FrameBuffer)) {
throw new RendererException("Framebuffer objects are not supported" +
" by the video hardware");
throw new RendererException("Framebuffer objects are not supported"
+ " by the video hardware");
}
// generate mipmaps for last FB if needed
if (context.boundFB != null) {
for (int i = 0; i < context.boundFB.getNumColorBuffers(); i++) {
@ -1518,14 +1499,18 @@ public class GLRenderer implements Renderer {
setTexture(0, rb.getTexture());
int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
if (gl2 != null) gl2.glEnable(textureType);
if (gl2 != null) {
gl2.glEnable(textureType);
}
glfbo.glGenerateMipmapEXT(textureType);
if (gl2 != null) gl2.glDisable(textureType);
if (gl2 != null) {
gl2.glDisable(textureType);
}
}
}
}
if (fb == null) {
if (fb == null) {
// unbind any fbos
if (context.boundFBO != 0) {
glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, 0);
@ -1579,7 +1564,7 @@ public class GLRenderer implements Renderer {
gl2.glReadBuffer(GL.GL_NONE);
context.boundReadBuf = -2;
}
}
}
} else {
if (fb.getNumColorBuffers() > maxFBOAttachs) {
throw new RendererException("Framebuffer has more color "
@ -1588,8 +1573,8 @@ public class GLRenderer implements Renderer {
}
if (fb.isMultiTarget()) {
if (!caps.contains(Caps.FrameBufferMRT)) {
throw new RendererException("Multiple render targets " +
" are not supported by the video hardware");
throw new RendererException("Multiple render targets "
+ " are not supported by the video hardware");
}
if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
throw new RendererException("Framebuffer has more"
@ -1694,14 +1679,6 @@ public class GLRenderer implements Renderer {
throw new RendererException("Multisample textures are not supported" +
" by the video hardware.");
}
if (type == Texture.Type.ThreeDimensional && gl2 == null) {
throw new RendererException("3D textures are not supported" +
" by the video hardware.");
} else if (type == Texture.Type.TwoDimensionalArray && !caps.contains(Caps.TextureArray)) {
throw new RendererException("Array textures are not supported" +
" by the video hardware.");
}
switch (type) {
case TwoDimensional:
@ -1711,13 +1688,21 @@ public class GLRenderer implements Renderer {
return GL.GL_TEXTURE_2D;
}
case TwoDimensionalArray:
if (!caps.contains(Caps.TextureArray)) {
throw new RendererException("Array textures are not supported"
+ " by the video hardware.");
}
if (samples > 1) {
return GLExt.GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
} else {
return GLExt.GL_TEXTURE_2D_ARRAY_EXT;
}
case ThreeDimensional:
return GL3.GL_TEXTURE_3D;
if (!caps.contains(Caps.OpenGL20)) {
throw new RendererException("3D textures are not supported" +
" by the video hardware.");
}
return GL2.GL_TEXTURE_3D;
case CubeMap:
if (face < 0) {
return GL.GL_TEXTURE_CUBE_MAP;
@ -2140,7 +2125,7 @@ public class GLRenderer implements Renderer {
//statistics.onVertexBufferUse(vb, false);
}
}
int usage = convertUsage(vb.getUsage());
vb.getData().rewind();
@ -2158,10 +2143,6 @@ public class GLRenderer implements Renderer {
break;
case Int:
case UnsignedInt:
if (!caps.contains(Caps.IntegerIndexBuffer)) {
throw new RendererException("32-bit index buffers are not supported by the video hardware");
}
glext.glBufferData(target, (IntBuffer) vb.getData(), usage);
break;
case Float:
@ -2230,108 +2211,103 @@ public class GLRenderer implements Renderer {
throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib");
}
int programId = context.boundShaderProgram;
if (context.boundShaderProgram <= 0) {
throw new IllegalStateException("Cannot render mesh without shader bound");
}
Attribute attrib = context.boundShader.getAttribute(vb.getBufferType());
int loc = attrib.getLocation();
if (loc == -1) {
return; // not defined
}
if (loc == -2) {
loc = gl.glGetAttribLocation(context.boundShaderProgram, "in" + vb.getBufferType().name());
if (programId > 0) {
Attribute attrib = context.boundShader.getAttribute(vb.getBufferType());
int loc = attrib.getLocation();
if (loc == -1) {
return; // not defined
// not really the name of it in the shader (inPosition) but
// the internal name of the enum (Position).
if (loc < 0) {
attrib.setLocation(-1);
return; // not available in shader.
} else {
attrib.setLocation(loc);
}
if (loc == -2) {
stringBuf.setLength(0);
stringBuf.append("in").append(vb.getBufferType().name()).append('\0');
loc = gl.glGetAttribLocation(programId, stringBuf.toString());
}
// not really the name of it in the shader (inPosition\0) but
// the internal name of the enum (Position).
if (loc < 0) {
attrib.setLocation(-1);
return; // not available in shader.
} else {
attrib.setLocation(loc);
}
}
if (vb.isInstanced()) {
if (!caps.contains(Caps.MeshInstancing)) {
throw new RendererException("Instancing is required, "
+ "but not supported by the "
+ "graphics hardware");
}
if (vb.isInstanced()) {
if (!caps.contains(Caps.MeshInstancing)) {
throw new RendererException("Instancing is required, "
+ "but not supported by the "
+ "graphics hardware");
}
int slotsRequired = 1;
if (vb.getNumComponents() > 4) {
if (vb.getNumComponents() % 4 != 0) {
throw new RendererException("Number of components in multi-slot "
+ "buffers must be divisible by 4");
}
slotsRequired = vb.getNumComponents() / 4;
}
int slotsRequired = 1;
if (vb.getNumComponents() > 4) {
if (vb.getNumComponents() % 4 != 0) {
throw new RendererException("Number of components in multi-slot "
+ "buffers must be divisible by 4");
}
slotsRequired = vb.getNumComponents() / 4;
}
if (vb.isUpdateNeeded() && idb == null) {
updateBufferData(vb);
}
if (vb.isUpdateNeeded() && idb == null) {
updateBufferData(vb);
}
VertexBuffer[] attribs = context.boundAttribs;
for (int i = 0; i < slotsRequired; i++) {
if (!context.attribIndexList.moveToNew(loc + i)) {
gl.glEnableVertexAttribArray(loc + i);
//System.out.println("Enabled ATTRIB IDX: "+loc);
}
VertexBuffer[] attribs = context.boundAttribs;
for (int i = 0; i < slotsRequired; i++) {
if (!context.attribIndexList.moveToNew(loc + i)) {
gl.glEnableVertexAttribArray(loc + i);
}
}
if (attribs[loc] != vb) {
// NOTE: Use id from interleaved buffer if specified
int bufId = idb != null ? idb.getId() : vb.getId();
assert bufId != -1;
if (context.boundArrayVBO != bufId) {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufId);
context.boundArrayVBO = bufId;
//statistics.onVertexBufferUse(vb, true);
} else {
//statistics.onVertexBufferUse(vb, false);
}
if (attribs[loc] != vb) {
// NOTE: Use id from interleaved buffer if specified
int bufId = idb != null ? idb.getId() : vb.getId();
assert bufId != -1;
if (context.boundArrayVBO != bufId) {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufId);
context.boundArrayVBO = bufId;
//statistics.onVertexBufferUse(vb, true);
} else {
//statistics.onVertexBufferUse(vb, false);
}
if (slotsRequired == 1) {
gl.glVertexAttribPointer(loc,
vb.getNumComponents(),
if (slotsRequired == 1) {
gl.glVertexAttribPointer(loc,
vb.getNumComponents(),
convertFormat(vb.getFormat()),
vb.isNormalized(),
vb.getStride(),
vb.getOffset());
} else {
for (int i = 0; i < slotsRequired; i++) {
// The pointer maps the next 4 floats in the slot.
// E.g.
// P1: XXXX____________XXXX____________
// P2: ____XXXX____________XXXX________
// P3: ________XXXX____________XXXX____
// P4: ____________XXXX____________XXXX
// stride = 4 bytes in float * 4 floats in slot * num slots
// offset = 4 bytes in float * 4 floats in slot * slot index
gl.glVertexAttribPointer(loc + i,
4,
convertFormat(vb.getFormat()),
vb.isNormalized(),
vb.getStride(),
vb.getOffset());
} else {
for (int i = 0; i < slotsRequired; i++) {
// The pointer maps the next 4 floats in the slot.
// E.g.
// P1: XXXX____________XXXX____________
// P2: ____XXXX____________XXXX________
// P3: ________XXXX____________XXXX____
// P4: ____________XXXX____________XXXX
// stride = 4 bytes in float * 4 floats in slot * num slots
// offset = 4 bytes in float * 4 floats in slot * slot index
gl.glVertexAttribPointer(loc + i,
4,
convertFormat(vb.getFormat()),
vb.isNormalized(),
4 * 4 * slotsRequired,
4 * 4 * i);
}
4 * 4 * slotsRequired,
4 * 4 * i);
}
}
for (int i = 0; i < slotsRequired; i++) {
int slot = loc + i;
if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) {
// non-instanced -> instanced
glext.glVertexAttribDivisorARB(slot, vb.getInstanceSpan());
} else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) {
// instanced -> non-instanced
glext.glVertexAttribDivisorARB(slot, 0);
}
attribs[slot] = vb;
for (int i = 0; i < slotsRequired; i++) {
int slot = loc + i;
if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) {
// non-instanced -> instanced
glext.glVertexAttribDivisorARB(slot, vb.getInstanceSpan());
} else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) {
// instanced -> non-instanced
glext.glVertexAttribDivisorARB(slot, 0);
}
attribs[slot] = vb;
}
} else {
throw new IllegalStateException("Cannot render mesh without shader bound");
}
}
@ -2354,6 +2330,21 @@ public class GLRenderer implements Renderer {
throw new IllegalArgumentException("Only index buffers are allowed as triangle lists.");
}
switch (indexBuf.getFormat()) {
case UnsignedShort:
// OK: Works on all platforms.
break;
case UnsignedInt:
// Requres extension on OpenGL ES 2.
if (!caps.contains(Caps.IntegerIndexBuffer)) {
throw new RendererException("32-bit index buffers are not supported by the video hardware");
}
break;
default:
// What is this?
throw new RendererException("Unexpected format for index buffer: " + indexBuf.getFormat());
}
if (indexBuf.isUpdateNeeded()) {
updateBufferData(indexBuf);
}

@ -80,7 +80,7 @@ public class NullRenderer implements Renderer {
public void setDepthRange(float start, float end) {
}
public void onFrame() {
public void postFrame() {
}
public void setWorldMatrix(Matrix4f worldMatrix) {

@ -335,7 +335,7 @@ public class IGLESShaderRenderer implements Renderer {
/**
* Called when a new frame has been rendered.
*/
public void onFrame() {
public void postFrame() {
logger.log(Level.FINE, "IGLESShaderRenderer onFrame");
//JmeIosGLES.checkGLErrorForced();
JmeIosGLES.checkGLError();

@ -832,17 +832,9 @@ public class JoglRenderer implements Renderer {
}
@Override
public void onFrame() {
public void postFrame() {
objManager.deleteUnused(this);
}
@Override
public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) {
}
@Override
public void setWorldMatrix(Matrix4f worldMatrix) {
}
/*********************************************************************\
|* Shaders *|
@ -997,14 +989,6 @@ public class JoglRenderer implements Renderer {
uniform.reset(); // e.g check location again
}
}
/*
* (Non-javadoc)
* Only used for fixed-function. Ignored.
*/
@Override
public void setLighting(LightList list) {
}
public int convertShaderType(Shader.ShaderType type) {
switch (type) {
@ -1248,11 +1232,6 @@ public class JoglRenderer implements Renderer {
/*********************************************************************\
|* Framebuffers *|
\*********************************************************************/
@Override
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
copyFrameBuffer(src, dst, true);
}
@Override
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
GL gl = GLContext.getCurrentGL();

@ -125,7 +125,7 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext
}
listener.update();
renderer.onFrame();
renderer.postFrame();
}

@ -351,6 +351,6 @@ public class JoglDisplay extends JoglAbstractDisplay {
}
listener.update();
renderer.onFrame();
renderer.postFrame();
}
}

@ -145,7 +145,7 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas
}
listener.update();
renderer.onFrame();
renderer.postFrame();
}

@ -239,7 +239,7 @@ public class JoglNewtDisplay extends JoglNewtAbstractDisplay {
}
listener.update();
renderer.onFrame();
renderer.postFrame();
}
}

@ -101,7 +101,7 @@ public class JoglOffscreenBuffer extends JoglContext implements Runnable {
listener.update();
checkGLError();
renderer.onFrame();
renderer.postFrame();
int frameRate = settings.getFrameRate();
if (frameRate >= 1) {

@ -343,11 +343,13 @@ public class LwjglGL implements GL, GL2 {
}
public int glGetAttribLocation(int param1, String param2) {
return GL20.glGetAttribLocation(param1, param2);
// NOTE: LWJGL requires null-terminated strings
return GL20.glGetAttribLocation(param1, param2 + "\0");
}
public int glGetUniformLocation(int param1, String param2) {
return GL20.glGetUniformLocation(param1, param2);
// NOTE: LWJGL requires null-terminated strings
return GL20.glGetUniformLocation(param1, param2 + "\0");
}
public void glShaderSource(int param1, String[] param2, IntBuffer param3) {

@ -424,11 +424,13 @@ public class LwjglRenderer {
logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples);
}
glGetInteger(GL_MAX_DRAW_BUFFERS, intBuf16);
maxMRTFBOAttachs = intBuf16.get(0);
if (maxMRTFBOAttachs > 1) {
caps.add(Caps.FrameBufferMRT);
logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
if (hasExtension("GL_ARB_draw_buffers")) {
glGetInteger(GL_MAX_DRAW_BUFFERS, intBuf16);
maxMRTFBOAttachs = intBuf16.get(0);
if (maxMRTFBOAttachs > 1) {
caps.add(Caps.FrameBufferMRT);
logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
}
}
}
@ -832,7 +834,7 @@ public class LwjglRenderer {
}
}
public void onFrame() {
public void postFrame() {
objManager.deleteUnused(this);
// statistics.clearFrame();
}
@ -1945,7 +1947,7 @@ public class LwjglRenderer {
// Image does not have mipmaps, but they are required.
// Generate from base level.
if (!caps.contains(Caps.OpenGL30)) {
if (!caps.contains(Caps.OpenGL30) && !caps.contains(Caps.OpenGLES20)) {
glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
img.setMipmapsGenerated(true);
} else {

@ -42,7 +42,7 @@ import java.util.EnumSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.lwjgl.opengl.ARBDepthBufferFloat.*;
import org.lwjgl.opengl.ARBES3Compatibility;
import static org.lwjgl.opengl.ARBES3Compatibility.*;
import static org.lwjgl.opengl.ARBHalfFloatPixel.*;
import static org.lwjgl.opengl.ARBTextureFloat.*;
import static org.lwjgl.opengl.ARBTextureMultisample.*;
@ -139,7 +139,7 @@ class TextureUtil {
// ETC1 support on regular OpenGL requires ES3 compatibility extension.
// NOTE: ETC2 is backwards compatible with ETC1, so we can
// upload ETC1 textures as ETC2.
setFormat(Format.ETC1, ARBES3Compatibility.GL_COMPRESSED_RGB8_ETC2, GL_RGB, GL_UNSIGNED_BYTE, true);
setFormat(Format.ETC1, GL_COMPRESSED_RGB8_ETC2, GL_RGB, GL_UNSIGNED_BYTE, true);
}
//sRGB formats

@ -184,7 +184,7 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
// Subclasses just call GLObjectManager clean up objects here
// it is safe .. for now.
renderer.onFrame();
renderer.postFrame();
}
/**

@ -125,7 +125,7 @@ public class LwjglOffscreenBuffer extends LwjglContext implements Runnable {
listener.update();
checkGLError();
renderer.onFrame();
renderer.postFrame();
int frameRate = settings.getFrameRate();
if (frameRate >= 1) {

Loading…
Cancel
Save