Renderer
is responsible for taking rendering commands and
- * executing them on the underlying video hardware.
- *
- * @author Kirill Vainer
- */
-public class IGLESShaderRenderer implements Renderer {
-
- private static final Logger logger = Logger.getLogger(IGLESShaderRenderer.class.getName());
- private static final boolean VALIDATE_SHADER = false;
-
- private final NativeObjectManager objManager = new NativeObjectManager();
- private final EnumSetnull
to disable lighting.
- *
- * @param lights The light list to set.
- */
- public void setLighting(LightList lights) {
- logger.log(Level.FINE, "IGLESShaderRenderer setLighting");
- }
-
- /**
- * Sets the shader to use for rendering.
- * If the shader has not been uploaded yet, it is compiled
- * and linked. If it has been uploaded, then the
- * uniform data is updated and the shader is set.
- *
- * @param shader The shader to use for rendering.
- */
- public void setShader(Shader shader) {
- logger.log(Level.FINE, "IGLESShaderRenderer setShader");
- if (shader == null) {
- throw new IllegalArgumentException("Shader cannot be null");
- } else {
- if (shader.isUpdateNeeded()) {
- updateShaderData(shader);
- }
-
- // NOTE: might want to check if any of the
- // sources need an update?
-
- assert shader.getId() > 0;
-
- updateShaderUniforms(shader);
- bindProgram(shader);
- }
- }
-
- /**
- * Deletes a shader. This method also deletes
- * the attached shader sources.
- *
- * @param shader Shader to delete.
- */
- public void deleteShader(Shader shader) {
- logger.log(Level.FINE, "IGLESShaderRenderer deleteShader");
- if (shader.getId() == -1) {
- logger.warning("Shader is not uploaded to GPU, cannot delete.");
- return;
- }
-
- for (ShaderSource source : shader.getSources()) {
- if (source.getId() != -1) {
- JmeIosGLES.glDetachShader(shader.getId(), source.getId());
- JmeIosGLES.checkGLError();
-
- deleteShaderSource(source);
- }
- }
-
- JmeIosGLES.glDeleteProgram(shader.getId());
- JmeIosGLES.checkGLError();
-
- statistics.onDeleteShader();
- shader.resetObject();
- }
-
- /**
- * Deletes the provided shader source.
- *
- * @param source The ShaderSource to delete.
- */
- public void deleteShaderSource(ShaderSource source) {
- logger.log(Level.FINE, "IGLESShaderRenderer deleteShaderSource");
- if (source.getId() < 0) {
- logger.warning("Shader source is not uploaded to GPU, cannot delete.");
- return;
- }
-
- source.clearUpdateNeeded();
-
- JmeIosGLES.glDeleteShader(source.getId());
- JmeIosGLES.checkGLError();
-
- source.resetObject();
- }
-
- /**
- * Copies contents from src to dst, scaling if necessary.
- */
- public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
- logger.log(Level.FINE, "IGLESShaderRenderer copyFrameBuffer");
- copyFrameBuffer(src, dst, true);
- }
-
- /**
- * Copies contents from src to dst, scaling if necessary.
- * set copyDepth to false to only copy the color buffers.
- */
- public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
- logger.warning("IGLESShaderRenderer copyFrameBuffer with depth TODO");
- throw new RendererException("Copy framebuffer not implemented yet.");
- }
-
- /**
- * Sets the framebuffer that will be drawn to.
- */
- public void setFrameBuffer(FrameBuffer fb) {
- logger.log(Level.FINE, "IGLESShaderRenderer setFrameBuffer");
- if (fb == null && mainFbOverride != null) {
- fb = mainFbOverride;
- }
-
- if (lastFb == fb) {
- if (fb == null || !fb.isUpdateNeeded()) {
- return;
- }
- }
-
- // generate mipmaps for last FB if needed
- if (lastFb != null) {
- for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
- RenderBuffer rb = lastFb.getColorBuffer(i);
- Texture tex = rb.getTexture();
- if (tex != null
- && tex.getMinFilter().usesMipMapLevels()) {
- setTexture(0, rb.getTexture());
-
-// int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
- int textureType = convertTextureType(tex.getType());
- JmeIosGLES.glGenerateMipmap(textureType);
- JmeIosGLES.checkGLError();
- }
- }
- }
-
- if (fb == null) {
- // unbind any fbos
- if (context.boundFBO != 0) {
- JmeIosGLES.glBindFramebuffer(JmeIosGLES.GL_FRAMEBUFFER, 0);
- JmeIosGLES.checkGLError();
-
- statistics.onFrameBufferUse(null, true);
-
- context.boundFBO = 0;
- }
-
- /*
- // select back buffer
- if (context.boundDrawBuf != -1) {
- glDrawBuffer(initialDrawBuf);
- context.boundDrawBuf = -1;
- }
- if (context.boundReadBuf != -1) {
- glReadBuffer(initialReadBuf);
- context.boundReadBuf = -1;
- }
- */
-
- lastFb = null;
- } else {
- if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
- throw new IllegalArgumentException("The framebuffer: " + fb
- + "\nDoesn't have any color/depth buffers");
- }
-
- if (fb.isUpdateNeeded()) {
- updateFrameBuffer(fb);
- }
-
- if (context.boundFBO != fb.getId()) {
- JmeIosGLES.glBindFramebuffer(JmeIosGLES.GL_FRAMEBUFFER, fb.getId());
- JmeIosGLES.checkGLError();
-
- statistics.onFrameBufferUse(fb, true);
-
- // update viewport to reflect framebuffer's resolution
- setViewPort(0, 0, fb.getWidth(), fb.getHeight());
-
- context.boundFBO = fb.getId();
- } else {
- statistics.onFrameBufferUse(fb, false);
- }
- if (fb.getNumColorBuffers() == 0) {
-// // make sure to select NONE as draw buf
-// // no color buffer attached. select NONE
- if (context.boundDrawBuf != -2) {
-// glDrawBuffer(GL_NONE);
- context.boundDrawBuf = -2;
- }
- if (context.boundReadBuf != -2) {
-// glReadBuffer(GL_NONE);
- context.boundReadBuf = -2;
- }
- } else {
- if (fb.getNumColorBuffers() > maxFBOAttachs) {
- throw new RendererException("Framebuffer has more color "
- + "attachments than are supported"
- + " by the video hardware!");
- }
- if (fb.isMultiTarget()) {
- if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
- throw new RendererException("Framebuffer has more"
- + " multi targets than are supported"
- + " by the video hardware!");
- }
-
- if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
- //intBuf16.clear();
- for (int i = 0; i < 16; i++) {
- intBuf16[i] = i < fb.getNumColorBuffers() ? JmeIosGLES.GL_COLOR_ATTACHMENT0 + i : 0;
- }
-
- //intBuf16.flip();// TODO: flip
-// glDrawBuffers(intBuf16);
- context.boundDrawBuf = 100 + fb.getNumColorBuffers();
- }
- } else {
- RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
- // select this draw buffer
- if (context.boundDrawBuf != rb.getSlot()) {
- JmeIosGLES.glActiveTexture(convertAttachmentSlot(rb.getSlot()));
- JmeIosGLES.checkGLError();
-
- context.boundDrawBuf = rb.getSlot();
- }
- }
- }
-
- assert fb.getId() >= 0;
- assert context.boundFBO == fb.getId();
-
- lastFb = fb;
-
- checkFrameBufferStatus(fb);
- }
- }
-
- /**
- * Set the framebuffer that will be set instead of the main framebuffer
- * when a call to setFrameBuffer(null) is made.
- *
- * @param fb
- */
- public void setMainFrameBufferOverride(FrameBuffer fb) {
- logger.log(Level.FINE, "IGLESShaderRenderer setMainFrameBufferOverride");
- mainFbOverride = fb;
- }
-
- /**
- * Reads the pixels currently stored in the specified framebuffer
- * into the given ByteBuffer object.
- * Only color pixels are transferred, the format is BGRA with 8 bits
- * per component. The given byte buffer should have at least
- * fb.getWidth() * fb.getHeight() * 4 bytes remaining.
- *
- * @param fb The framebuffer to read from
- * @param byteBuf The bytebuffer to transfer color data to
- */
- public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
- logger.log(Level.FINE, "IGLESShaderRenderer readFrameBuffer");
- if (fb != null) {
- RenderBuffer rb = fb.getColorBuffer();
- if (rb == null) {
- throw new IllegalArgumentException("Specified framebuffer"
- + " does not have a colorbuffer");
- }
-
- setFrameBuffer(fb);
- } else {
- setFrameBuffer(null);
- }
-
- //JmeIosGLES.glReadPixels2(vpX, vpY, vpW, vpH, JmeIosGLES.GL_RGBA, JmeIosGLES.GL_UNSIGNED_BYTE, byteBuf.array(), 0, vpW * vpH * 4);
- JmeIosGLES.glReadPixels(vpX, vpY, vpW, vpH, JmeIosGLES.GL_RGBA, JmeIosGLES.GL_UNSIGNED_BYTE, byteBuf);
- JmeIosGLES.checkGLError();
- }
-
- /**
- * Deletes a framebuffer and all attached renderbuffers
- */
- public void deleteFrameBuffer(FrameBuffer fb) {
- logger.log(Level.FINE, "IGLESShaderRenderer deleteFrameBuffer");
- if (fb.getId() != -1) {
- if (context.boundFBO == fb.getId()) {
- JmeIosGLES.glBindFramebuffer(JmeIosGLES.GL_FRAMEBUFFER, 0);
- JmeIosGLES.checkGLError();
-
- context.boundFBO = 0;
- }
-
- if (fb.getDepthBuffer() != null) {
- deleteRenderBuffer(fb, fb.getDepthBuffer());
- }
- if (fb.getColorBuffer() != null) {
- deleteRenderBuffer(fb, fb.getColorBuffer());
- }
-
- intBuf1[0] = fb.getId();
- JmeIosGLES.glDeleteFramebuffers(1, intBuf1, 0);
- JmeIosGLES.checkGLError();
-
- fb.resetObject();
-
- statistics.onDeleteFrameBuffer();
- }
- }
-
- /**
- * Sets the texture to use for the given texture unit.
- */
- public void setTexture(int unit, Texture tex) {
- logger.log(Level.FINE, "IGLESShaderRenderer setTexture");
- Image image = tex.getImage();
- if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated()) ) {
- updateTexImageData(image, tex.getType());
- }
-
- int texId = image.getId();
- assert texId != -1;
-
- if (texId == -1) {
- logger.warning("error: texture image has -1 id");
- }
-
- Image[] textures = context.boundTextures;
-
- int type = convertTextureType(tex.getType());
- if (textures[unit] != image) {
- if (context.boundTextureUnit != unit) {
- JmeIosGLES.glActiveTexture(JmeIosGLES.GL_TEXTURE0 + unit);
- context.boundTextureUnit = unit;
- }
-
- JmeIosGLES.glBindTexture(type, texId);
- JmeIosGLES.checkGLError();
-
- textures[unit] = image;
-
- statistics.onTextureUse(tex.getImage(), true);
- } else {
- statistics.onTextureUse(tex.getImage(), false);
- }
-
- setupTextureParams(tex);
- }
-
- /**
- * Modify the given Texture tex with the given Image. The image will be put at x and y into the texture.
- *
- * @param tex the Texture that will be modified
- * @param pixels the source Image data to copy data from
- * @param x the x position to put the image into the texture
- * @param y the y position to put the image into the texture
- */
- public void modifyTexture(Texture tex, Image pixels, int x, int y) {
- logger.log(Level.FINE, "IGLESShaderRenderer modifyTexture");
- setTexture(0, tex);
- TextureUtil.uploadSubTexture(pixels, convertTextureType(tex.getType()), 0, x, y);
- }
-
- /**
- * Deletes a texture from the GPU.
- */
- public void deleteImage(Image image) {
- logger.log(Level.FINE, "IGLESShaderRenderer deleteImage");
- int texId = image.getId();
- if (texId != -1) {
- intBuf1[0] = texId;
-
- JmeIosGLES.glDeleteTextures(1, intBuf1, 0);
- JmeIosGLES.checkGLError();
-
- image.resetObject();
-
- statistics.onDeleteTexture();
- }
- }
-
- /**
- * Uploads a vertex buffer to the GPU.
- *
- * @param vb The vertex buffer to upload
- */
- public void updateBufferData(VertexBuffer vb) {
- logger.log(Level.FINE, "IGLESShaderRenderer updateBufferData");
- int bufId = vb.getId();
- boolean created = false;
- if (bufId == -1) {
- // create buffer
- JmeIosGLES.glGenBuffers(1, intBuf1, 0);
- JmeIosGLES.checkGLError();
-
- bufId = intBuf1[0];
- vb.setId(bufId);
- objManager.registerObject(vb);
-
- created = true;
- }
-
- // bind buffer
- int target;
- if (vb.getBufferType() == VertexBuffer.Type.Index) {
- target = JmeIosGLES.GL_ELEMENT_ARRAY_BUFFER;
- if (context.boundElementArrayVBO != bufId) {
- JmeIosGLES.glBindBuffer(target, bufId);
- JmeIosGLES.checkGLError();
-
- context.boundElementArrayVBO = bufId;
- }
- } else {
- target = JmeIosGLES.GL_ARRAY_BUFFER;
- if (context.boundArrayVBO != bufId) {
- JmeIosGLES.glBindBuffer(target, bufId);
- JmeIosGLES.checkGLError();
-
- context.boundArrayVBO = bufId;
- }
- }
-
- int usage = convertUsage(vb.getUsage());
- vb.getData().rewind();
-
- if (created || vb.hasDataSizeChanged()) {
- // upload data based on format
- int size = vb.getData().limit() * vb.getFormat().getComponentSize();
-
- switch (vb.getFormat()) {
- case Byte:
- case UnsignedByte:
- JmeIosGLES.glBufferData(target, size, (ByteBuffer) vb.getData(), usage);
- JmeIosGLES.checkGLError();
- break;
- case Short:
- case UnsignedShort:
- JmeIosGLES.glBufferData(target, size, (ShortBuffer) vb.getData(), usage);
- JmeIosGLES.checkGLError();
- break;
- case Int:
- case UnsignedInt:
- JmeIosGLES.glBufferData(target, size, (IntBuffer) vb.getData(), usage);
- JmeIosGLES.checkGLError();
- break;
- case Float:
- JmeIosGLES.glBufferData(target, size, (FloatBuffer) vb.getData(), usage);
- JmeIosGLES.checkGLError();
- break;
- default:
- throw new RuntimeException("Unknown buffer format.");
- }
- } else {
- int size = vb.getData().limit() * vb.getFormat().getComponentSize();
-
- switch (vb.getFormat()) {
- case Byte:
- case UnsignedByte:
- JmeIosGLES.glBufferSubData(target, 0, size, (ByteBuffer) vb.getData());
- JmeIosGLES.checkGLError();
- break;
- case Short:
- case UnsignedShort:
- JmeIosGLES.glBufferSubData(target, 0, size, (ShortBuffer) vb.getData());
- JmeIosGLES.checkGLError();
- break;
- case Int:
- case UnsignedInt:
- JmeIosGLES.glBufferSubData(target, 0, size, (IntBuffer) vb.getData());
- JmeIosGLES.checkGLError();
- break;
- case Float:
- JmeIosGLES.glBufferSubData(target, 0, size, (FloatBuffer) vb.getData());
- JmeIosGLES.checkGLError();
- break;
- default:
- throw new RuntimeException("Unknown buffer format.");
- }
- }
- vb.clearUpdateNeeded();
- }
-
- /**
- * Deletes a vertex buffer from the GPU.
- * @param vb The vertex buffer to delete
- */
- public void deleteBuffer(VertexBuffer vb) {
- logger.log(Level.FINE, "IGLESShaderRenderer deleteBuffer");
- int bufId = vb.getId();
- if (bufId != -1) {
- // delete buffer
- intBuf1[0] = bufId;
-
- JmeIosGLES.glDeleteBuffers(1, intBuf1, 0);
- JmeIosGLES.checkGLError();
-
- vb.resetObject();
- }
- }
-
- /**
- * Renders count
meshes, with the geometry data supplied.
- * The shader which is currently set with setShader
is
- * responsible for transforming the input verticies into clip space
- * and shading it based on the given vertex attributes.
- * The int variable gl_InstanceID can be used to access the current
- * instance of the mesh being rendered inside the vertex shader.
- *
- * @param mesh The mesh to render
- * @param lod The LOD level to use, see {@link Mesh#setLodLevels(com.jme3.scene.VertexBuffer[]) }.
- * @param count Number of mesh instances to render
- */
- public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
- logger.log(Level.FINE, "IGLESShaderRenderer renderMesh");
- if (mesh.getVertexCount() == 0) {
- return;
- }
- /*
- * NOTE: not supported in OpenGL ES 2.0.
- if (context.pointSize != mesh.getPointSize()) {
- GLES10.glPointSize(mesh.getPointSize());
- context.pointSize = mesh.getPointSize();
- }
- */
- if (context.lineWidth != mesh.getLineWidth()) {
- JmeIosGLES.glLineWidth(mesh.getLineWidth());
- JmeIosGLES.checkGLError();
- context.lineWidth = mesh.getLineWidth();
- }
-
- statistics.onMeshDrawn(mesh, lod);
-// if (GLContext.getCapabilities().GL_ARB_vertex_array_object){
-// renderMeshVertexArray(mesh, lod, count);
-// }else{
-
- if (useVBO) {
- renderMeshDefault(mesh, lod, count);
- } else {
- renderMeshVertexArray(mesh, lod, count);
- }
- }
-
- /**
- * Resets all previously used {@link NativeObject Native Objects} on this Renderer.
- * The state of the native objects is reset in such way, that using
- * them again will cause the renderer to reupload them.
- * Call this method when you know the GL context is going to shutdown.
- *
- * @see NativeObject#resetObject()
- */
- public void resetGLObjects() {
- logger.log(Level.FINE, "IGLESShaderRenderer resetGLObjects");
- objManager.resetObjects();
- statistics.clearMemory();
- boundShader = null;
- lastFb = null;
- context.reset();
- }
-
- /**
- * Deletes all previously used {@link NativeObject Native Objects} on this Renderer, and
- * then resets the native objects.
- *
- * @see #resetGLObjects()
- * @see NativeObject#deleteObject(java.lang.Object)
- */
- public void cleanup() {
- logger.log(Level.FINE, "IGLESShaderRenderer cleanup");
- objManager.deleteAllObjects(this);
- statistics.clearMemory();
- }
-
- /**
- * Sets the alpha to coverage state.
- * - * When alpha coverage and multi-sampling is enabled, - * each pixel will contain alpha coverage in all - * of its subsamples, which is then combined when - * other future alpha-blended objects are rendered. - *
- *- * Alpha-to-coverage is useful for rendering transparent objects - * without having to worry about sorting them. - *
- */ - public void setAlphaToCoverage(boolean value) { - logger.log(Level.FINE, "IGLESShaderRenderer setAlphaToCoverage"); - if (value) { - JmeIosGLES.glEnable(JmeIosGLES.GL_SAMPLE_ALPHA_TO_COVERAGE); - JmeIosGLES.checkGLError(); - } else { - JmeIosGLES.glDisable(JmeIosGLES.GL_SAMPLE_ALPHA_TO_COVERAGE); - JmeIosGLES.checkGLError(); - } - } - - - /* ------------------------------------------------------------------------------ */ - - - public void initialize() { - Level store = logger.getLevel(); - logger.setLevel(Level.FINE); - - logger.log(Level.FINE, "Vendor: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_VENDOR)); - logger.log(Level.FINE, "Renderer: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_RENDERER)); - logger.log(Level.FINE, "Version: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_VERSION)); - logger.log(Level.FINE, "Shading Language Version: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_SHADING_LANGUAGE_VERSION)); - - /* - // Fix issue in TestRenderToMemory when GL_FRONT is the main - // buffer being used. - initialDrawBuf = glGetInteger(GL_DRAW_BUFFER); - initialReadBuf = glGetInteger(GL_READ_BUFFER); - - // XXX: This has to be GL_BACK for canvas on Mac - // Since initialDrawBuf is GL_FRONT for pbuffer, gotta - // change this value later on ... -// initialDrawBuf = GL_BACK; -// initialReadBuf = GL_BACK; - */ - - // Check OpenGL version - int openGlVer = extractVersion("OpenGL ES ", JmeIosGLES.glGetString(JmeIosGLES.GL_VERSION)); - if (openGlVer == -1) { - glslVer = -1; - throw new UnsupportedOperationException("OpenGL ES 2.0+ is required for IGLESShaderRenderer!"); - } - - // Check shader language version - glslVer = extractVersion("OpenGL ES GLSL ES ", JmeIosGLES.glGetString(JmeIosGLES.GL_SHADING_LANGUAGE_VERSION)); - switch (glslVer) { - // TODO: When new versions of OpenGL ES shader language come out, - // update this. - default: - caps.add(Caps.GLSL100); - break; - } - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16, 0); - vertexTextureUnits = intBuf16[0]; - logger.log(Level.FINE, "VTF Units: {0}", vertexTextureUnits); - if (vertexTextureUnits > 0) { - caps.add(Caps.VertexTextureFetch); - } - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_TEXTURE_IMAGE_UNITS, intBuf16, 0); - fragTextureUnits = intBuf16[0]; - logger.log(Level.FINE, "Texture Units: {0}", fragTextureUnits); - - // Multiply vector count by 4 to get float count. - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VERTEX_UNIFORM_VECTORS, intBuf16, 0); - vertexUniforms = intBuf16[0] * 4; - logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_FRAGMENT_UNIFORM_VECTORS, intBuf16, 0); - fragUniforms = intBuf16[0] * 4; - logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VARYING_VECTORS, intBuf16, 0); - int varyingFloats = intBuf16[0] * 4; - logger.log(Level.FINER, "Varying Floats: {0}", varyingFloats); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VERTEX_ATTRIBS, intBuf16, 0); - vertexAttribs = intBuf16[0]; - logger.log(Level.FINE, "Vertex Attributes: {0}", vertexAttribs); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_SUBPIXEL_BITS, intBuf16, 0); - int subpixelBits = intBuf16[0]; - logger.log(Level.FINE, "Subpixel Bits: {0}", subpixelBits); - -// GLES10.glGetIntegerv(GLES10.GL_MAX_ELEMENTS_VERTICES, intBuf16); -// maxVertCount = intBuf16.get(0); -// logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount); -// -// GLES10.glGetIntegerv(GLES10.GL_MAX_ELEMENTS_INDICES, intBuf16); -// maxTriCount = intBuf16.get(0); -// logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_TEXTURE_SIZE, intBuf16, 0); - maxTexSize = intBuf16[0]; - logger.log(Level.FINE, "Maximum Texture Resolution: {0}", maxTexSize); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_CUBE_MAP_TEXTURE_SIZE, intBuf16, 0); - maxCubeTexSize = intBuf16[0]; - logger.log(Level.FINE, "Maximum CubeMap Resolution: {0}", maxCubeTexSize); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_RENDERBUFFER_SIZE, intBuf16, 0); - maxRBSize = intBuf16[0]; - logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize); - - /* - if (ctxCaps.GL_ARB_color_buffer_float){ - // XXX: Require both 16 and 32 bit float support for FloatColorBuffer. - if (ctxCaps.GL_ARB_half_float_pixel){ - caps.add(Caps.FloatColorBuffer); - } - } - - if (ctxCaps.GL_ARB_depth_buffer_float){ - caps.add(Caps.FloatDepthBuffer); - } - - if (ctxCaps.GL_ARB_draw_instanced) - caps.add(Caps.MeshInstancing); - - if (ctxCaps.GL_ARB_texture_buffer_object) - caps.add(Caps.TextureBuffer); - - if (ctxCaps.GL_ARB_texture_float){ - if (ctxCaps.GL_ARB_half_float_pixel){ - caps.add(Caps.FloatTexture); - } - } - - if (ctxCaps.GL_EXT_packed_float){ - caps.add(Caps.PackedFloatColorBuffer); - if (ctxCaps.GL_ARB_half_float_pixel){ - // because textures are usually uploaded as RGB16F - // need half-float pixel - caps.add(Caps.PackedFloatTexture); - } - } - - if (ctxCaps.GL_EXT_texture_array) - caps.add(Caps.TextureArray); - - if (ctxCaps.GL_EXT_texture_shared_exponent) - caps.add(Caps.SharedExponentTexture); - - if (ctxCaps.GL_EXT_framebuffer_object){ - caps.add(Caps.FrameBuffer); - - glGetInteger(GL_MAX_RENDERBUFFER_SIZE_EXT, intBuf16); - maxRBSize = intBuf16.get(0); - logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize); - - glGetInteger(GL_MAX_COLOR_ATTACHMENTS_EXT, intBuf16); - maxFBOAttachs = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs); - - if (ctxCaps.GL_EXT_framebuffer_multisample){ - caps.add(Caps.FrameBufferMultisample); - - glGetInteger(GL_MAX_SAMPLES_EXT, intBuf16); - maxFBOSamples = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples); - } - - if (ctxCaps.GL_ARB_draw_buffers){ - caps.add(Caps.FrameBufferMRT); - glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16); - maxMRTFBOAttachs = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs); - } - } - - if (ctxCaps.GL_ARB_multisample){ - glGetInteger(ARBMultisample.GL_SAMPLE_BUFFERS_ARB, intBuf16); - boolean available = intBuf16.get(0) != 0; - glGetInteger(ARBMultisample.GL_SAMPLES_ARB, intBuf16); - int samples = intBuf16.get(0); - logger.log(Level.FINER, "Samples: {0}", samples); - boolean enabled = glIsEnabled(ARBMultisample.GL_MULTISAMPLE_ARB); - if (samples > 0 && available && !enabled){ - glEnable(ARBMultisample.GL_MULTISAMPLE_ARB); - } - } - */ - - String extensions = JmeIosGLES.glGetString(JmeIosGLES.GL_EXTENSIONS); - logger.log(Level.FINE, "GL_EXTENSIONS: {0}", extensions); - - // Get number of compressed formats available. - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_NUM_COMPRESSED_TEXTURE_FORMATS, intBuf16, 0); - int numCompressedFormats = intBuf16[0]; - - // Allocate buffer for compressed formats. - int[] compressedFormats = new int[numCompressedFormats]; - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_COMPRESSED_TEXTURE_FORMATS, compressedFormats, 0); - - // Check for errors after all glGet calls. - JmeIosGLES.checkGLError(); - - // Print compressed formats. - for (int i = 0; i < numCompressedFormats; i++) { - logger.log(Level.FINE, "Compressed Texture Formats: {0}", compressedFormats[i]); - } - - TextureUtil.loadTextureFeatures(extensions); - - applyRenderState(RenderState.DEFAULT); - JmeIosGLES.glDisable(JmeIosGLES.GL_DITHER); - JmeIosGLES.checkGLError(); - - logger.log(Level.FINE, "Caps: {0}", caps); - logger.setLevel(store); - - uintIndexSupport = extensions.contains("GL_OES_element_index_uint"); - logger.log(Level.FINE, "Support for UInt index: {0}", uintIndexSupport); - } - - - /* ------------------------------------------------------------------------------ */ - - - private int extractVersion(String prefixStr, String versionStr) { - if (versionStr != null) { - int spaceIdx = versionStr.indexOf(" ", prefixStr.length()); - if (spaceIdx >= 1) { - versionStr = versionStr.substring(prefixStr.length(), spaceIdx).trim(); - } else { - versionStr = versionStr.substring(prefixStr.length()).trim(); - } - float version = Float.parseFloat(versionStr); - return (int) (version * 100); - } else { - return -1; - } - } - - private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) { - intBuf1[0] = rb.getId(); - JmeIosGLES.glDeleteRenderbuffers(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - } - - private int convertUsage(Usage usage) { - switch (usage) { - case Static: - return JmeIosGLES.GL_STATIC_DRAW; - case Dynamic: - return JmeIosGLES.GL_DYNAMIC_DRAW; - case Stream: - return JmeIosGLES.GL_STREAM_DRAW; - default: - throw new RuntimeException("Unknown usage type."); - } - } - - - protected void bindProgram(Shader shader) { - int shaderId = shader.getId(); - if (context.boundShaderProgram != shaderId) { - JmeIosGLES.glUseProgram(shaderId); - JmeIosGLES.checkGLError(); - - statistics.onShaderUse(shader, true); - boundShader = shader; - context.boundShaderProgram = shaderId; - } else { - statistics.onShaderUse(shader, false); - } - } - - protected void updateShaderUniforms(Shader shader) { - ListMapuploadTextureBitmap
uploads a native android bitmap
- */
- /*
- public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips) {
- uploadTextureBitmap(target, bitmap, needMips, false, 0, 0);
- }
-
- /**
- * uploadTextureBitmap
uploads a native android bitmap
- */
- /*
- public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips, boolean subTexture, int x, int y) {
- boolean recycleBitmap = false;
- //TODO, maybe this should raise an exception when NPOT is not supported
-
- boolean willCompress = ENABLE_COMPRESSION && ETC1support && !bitmap.hasAlpha();
- if (needMips && willCompress) {
- // Image is compressed and mipmaps are desired, generate them
- // using software.
- buildMipmap(bitmap, willCompress);
- } else {
- if (willCompress) {
- // Image is compressed but mipmaps are not desired, upload directly.
- logger.log(Level.FINEST, " - Uploading compressed bitmap. Mipmaps are not generated.");
- uploadBitmapAsCompressed(target, 0, bitmap, subTexture, x, y);
-
- } else {
- // Image is not compressed, mipmaps may or may not be desired.
- logger.log(Level.FINEST, " - Uploading bitmap directly.{0}",
- (needMips
- ? " Mipmaps will be generated in HARDWARE"
- : " Mipmaps are not generated."));
- if (subTexture) {
- System.err.println("x : " + x + " y :" + y + " , " + bitmap.getWidth() + "/" + bitmap.getHeight());
- GLUtils.texSubImage2D(target, 0, x, y, bitmap);
- JmeIosGLES.checkGLError();
- } else {
- GLUtils.texImage2D(target, 0, bitmap, 0);
- JmeIosGLES.checkGLError();
- }
-
- if (needMips) {
- // No pregenerated mips available,
- // generate from base level if required
- JmeIosGLES.glGenerateMipmap(target);
- JmeIosGLES.checkGLError();
- }
- }
- }
-
- if (recycleBitmap) {
- bitmap.recycle();
- }
- }
- */
-
- public static void uploadTextureAny(Image img, int target, int index, boolean needMips) {
- /*
- if (img.getEfficentData() instanceof AndroidImageInfo) {
- logger.log(Level.FINEST, " === Uploading image {0}. Using BITMAP PATH === ", img);
- // If image was loaded from asset manager, use fast path
- AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData();
- uploadTextureBitmap(target, imageInfo.getBitmap(), needMips);
- } else {
- */
- logger.log(Level.FINEST, " === Uploading image {0}. Using BUFFER PATH === ", img);
- boolean wantGeneratedMips = needMips && !img.hasMipmaps();
- if (wantGeneratedMips && img.getFormat().isCompressed()) {
- logger.log(Level.WARNING, "Generating mipmaps is only"
- + " supported for Bitmap based or non-compressed images!");
- }
-
- // Upload using slower path
- logger.log(Level.FINEST, " - Uploading bitmap directly.{0}",
- (wantGeneratedMips
- ? " Mipmaps will be generated in HARDWARE"
- : " Mipmaps are not generated."));
-
- uploadTexture(img, target, index);
-
- // Image was uploaded using slower path, since it is not compressed,
- // then compress it
- if (wantGeneratedMips) {
- // No pregenerated mips available,
- // generate from base level if required
- JmeIosGLES.glGenerateMipmap(target);
- JmeIosGLES.checkGLError();
- }
- //}
- }
-
- private static void unsupportedFormat(Format fmt) {
- throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware.");
- }
-
- public static IosGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException {
- IosGLImageFormat imageFormat = new IosGLImageFormat();
- switch (fmt) {
- case Depth32:
- case Depth32F:
- throw new UnsupportedOperationException("The image format '"
- + fmt + "' is not supported by OpenGL ES 2.0 specification.");
- case Alpha8:
- imageFormat.format = JmeIosGLES.GL_ALPHA;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- if (RGBA8) {
- imageFormat.renderBufferStorageFormat = GL_RGBA8;
- } else {
- // Highest precision alpha supported by vanilla OGLES2
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4;
- }
- break;
- case Luminance8:
- imageFormat.format = JmeIosGLES.GL_LUMINANCE;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- if (RGBA8) {
- imageFormat.renderBufferStorageFormat = GL_RGBA8;
- } else {
- // Highest precision luminance supported by vanilla OGLES2
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565;
- }
- break;
- case Luminance8Alpha8:
- imageFormat.format = JmeIosGLES.GL_LUMINANCE_ALPHA;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- if (RGBA8) {
- imageFormat.renderBufferStorageFormat = GL_RGBA8;
- } else {
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4;
- }
- break;
- case RGB565:
- imageFormat.format = JmeIosGLES.GL_RGB;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT_5_6_5;
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565;
- break;
- case RGB5A1:
- imageFormat.format = JmeIosGLES.GL_RGBA;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT_5_5_5_1;
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB5_A1;
- break;
- case RGB8:
- imageFormat.format = JmeIosGLES.GL_RGB;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- if (RGBA8) {
- imageFormat.renderBufferStorageFormat = GL_RGBA8;
- } else {
- // Fallback: Use RGB565 if RGBA8 is not available.
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565;
- }
- break;
- case BGR8:
- imageFormat.format = JmeIosGLES.GL_RGB;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- if (RGBA8) {
- imageFormat.renderBufferStorageFormat = GL_RGBA8;
- } else {
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565;
- }
- break;
- case RGBA8:
- imageFormat.format = JmeIosGLES.GL_RGBA;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- if (RGBA8) {
- imageFormat.renderBufferStorageFormat = GL_RGBA8;
- } else {
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4;
- }
- break;
- case Depth:
- case Depth16:
- if (!DEPTH_TEXTURE) {
- unsupportedFormat(fmt);
- }
- imageFormat.format = JmeIosGLES.GL_DEPTH_COMPONENT;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT;
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_DEPTH_COMPONENT16;
- break;
- case Depth24:
- case Depth24Stencil8:
- if (!DEPTH_TEXTURE) {
- unsupportedFormat(fmt);
- }
- if (DEPTH24_STENCIL8) {
- // NEW: True Depth24 + Stencil8 format.
- imageFormat.format = GL_DEPTH_STENCIL_OES;
- imageFormat.dataType = GL_UNSIGNED_INT_24_8_OES;
- imageFormat.renderBufferStorageFormat = GL_DEPTH24_STENCIL8_OES;
- } else {
- // Vanilla OGLES2, only Depth16 available.
- imageFormat.format = JmeIosGLES.GL_DEPTH_COMPONENT;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT;
- imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_DEPTH_COMPONENT16;
- }
- break;
- case DXT1:
- if (!DXT1) {
- unsupportedFormat(fmt);
- }
- imageFormat.format = GL_DXT1;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- imageFormat.compress = true;
- break;
- case DXT1A:
- if (!DXT1) {
- unsupportedFormat(fmt);
- }
- imageFormat.format = GL_DXT1A;
- imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE;
- imageFormat.compress = true;
- break;
- default:
- throw new UnsupportedOperationException("Unrecognized format: " + fmt);
- }
- return imageFormat;
- }
-
- public static class IosGLImageFormat {
-
- boolean compress = false;
- int format = -1;
- int renderBufferStorageFormat = -1;
- int dataType = -1;
- }
-
- private static void uploadTexture(Image img,
- int target,
- int index) {
-
- /*
- if (img.getEfficentData() instanceof AndroidImageInfo) {
- throw new RendererException("This image uses efficient data. "
- + "Use uploadTextureBitmap instead.");
- }
- */
-
- // Otherwise upload image directly.
- // Prefer to only use power of 2 textures here to avoid errors.
- Image.Format fmt = img.getFormat();
- ByteBuffer data;
- if (index >= 0 || img.getData() != null && img.getData().size() > 0) {
- data = img.getData(index);
- } else {
- data = null;
- }
-
- int width = img.getWidth();
- int height = img.getHeight();
-
- if (!NPOT && img.isNPOT()) {
- // Check if texture is POT
- throw new RendererException("Non-power-of-2 textures "
- + "are not supported by the video hardware "
- + "and no scaling path available for image: " + img);
- }
- IosGLImageFormat imageFormat = getImageFormat(fmt);
-
- if (data != null) {
- JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1);
- JmeIosGLES.checkGLError();
- }
-
- int[] mipSizes = img.getMipMapSizes();
- int pos = 0;
- if (mipSizes == null) {
- if (data != null) {
- mipSizes = new int[]{data.capacity()};
- } else {
- mipSizes = new int[]{width * height * fmt.getBitsPerPixel() / 8};
- }
- }
-
- for (int i = 0; i < mipSizes.length; i++) {
- int mipWidth = Math.max(1, width >> i);
- int mipHeight = Math.max(1, height >> i);
-
- if (data != null) {
- data.position(pos);
- data.limit(pos + mipSizes[i]);
- }
-
- if (imageFormat.compress && data != null) {
- JmeIosGLES.glCompressedTexImage2D(target,
- i,
- imageFormat.format,
- mipWidth,
- mipHeight,
- 0,
- data.remaining(),
- data);
- } else {
- JmeIosGLES.glTexImage2D(target,
- i,
- imageFormat.format,
- mipWidth,
- mipHeight,
- 0,
- imageFormat.format,
- imageFormat.dataType,
- data);
- }
- JmeIosGLES.checkGLError();
-
- pos += mipSizes[i];
- }
- }
-
- /**
- * Update the texture currently bound to target at with data from the given
- * Image at position x and y. The parameter index is used as the zoffset in
- * case a 3d texture or texture 2d array is being updated.
- *
- * @param image Image with the source data (this data will be put into the
- * texture)
- * @param target the target texture
- * @param index the mipmap level to update
- * @param x the x position where to put the image in the texture
- * @param y the y position where to put the image in the texture
- */
- public static void uploadSubTexture(
- Image img,
- int target,
- int index,
- int x,
- int y) {
- //TODO:
- /*
- if (img.getEfficentData() instanceof AndroidImageInfo) {
- AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData();
- uploadTextureBitmap(target, imageInfo.getBitmap(), true, true, x, y);
- return;
- }
- */
-
- // Otherwise upload image directly.
- // Prefer to only use power of 2 textures here to avoid errors.
- Image.Format fmt = img.getFormat();
- ByteBuffer data;
- if (index >= 0 || img.getData() != null && img.getData().size() > 0) {
- data = img.getData(index);
- } else {
- data = null;
- }
-
- int width = img.getWidth();
- int height = img.getHeight();
-
- if (!NPOT && img.isNPOT()) {
- // Check if texture is POT
- throw new RendererException("Non-power-of-2 textures "
- + "are not supported by the video hardware "
- + "and no scaling path available for image: " + img);
- }
- IosGLImageFormat imageFormat = getImageFormat(fmt);
-
- if (data != null) {
- JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1);
- JmeIosGLES.checkGLError();
- }
-
- int[] mipSizes = img.getMipMapSizes();
- int pos = 0;
- if (mipSizes == null) {
- if (data != null) {
- mipSizes = new int[]{data.capacity()};
- } else {
- mipSizes = new int[]{width * height * fmt.getBitsPerPixel() / 8};
- }
- }
-
- for (int i = 0; i < mipSizes.length; i++) {
- int mipWidth = Math.max(1, width >> i);
- int mipHeight = Math.max(1, height >> i);
-
- if (data != null) {
- data.position(pos);
- data.limit(pos + mipSizes[i]);
- }
-
- if (imageFormat.compress && data != null) {
- JmeIosGLES.glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, data.remaining(), data);
- JmeIosGLES.checkGLError();
- } else {
- JmeIosGLES.glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, imageFormat.dataType, data);
- JmeIosGLES.checkGLError();
- }
-
- pos += mipSizes[i];
- }
- }
-}
diff --git a/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg b/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg
index 4e4052447..e9d79a459 100644
--- a/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg
+++ b/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg
@@ -2,7 +2,9 @@ INCLUDE com/jme3/asset/General.cfg
# IOS specific loaders
LOADER com.jme3.system.ios.IosImageLoader : jpg, bmp, gif, png, jpeg
-LOADER com.jme3.material.plugins.J3MLoader : j3m, j3md
+LOADER com.jme3.audio.plugins.OGGLoader : ogg
+LOADER com.jme3.material.plugins.J3MLoader : j3m
+LOADER com.jme3.material.plugins.J3MLoader : j3md
LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, glsl, glsllib
LOADER com.jme3.export.binary.BinaryImporter : j3o
LOADER com.jme3.font.plugins.BitmapFontLoader : fnt