Android OpenGL ES read texture pixels - java

The preview from my camera is rendered to a texture. I have the textureId and am trying to render the texture on a FBO so I can glReadPixels.
When I do actually read the pixels, all of them appear to be black though.
This is the code I am using at the moment:
//called when the camera first connects to the texture
public void initBackBuffer()
{
// For use in getFramePixels()
intBuffer = ByteBuffer.allocateDirect(width *
height * 4)
.order(ByteOrder.nativeOrder())
.asIntBuffer();
IntBuffer framebuffer = IntBuffer.allocate(1);
glGenFramebuffers(1, framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get(0));
int status = glGetError();
if(status != GL_NO_ERROR)
{
Log.e("RENDERER", status + "");
}
IntBuffer depthBufferName = IntBuffer.allocate(1);
glGenRenderbuffers(1, depthBufferName);
glBindRenderbuffer(GL_RENDERBUFFER, depthBufferName.get(0));
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
depthBufferName.get(0));
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
mTangoCameraTexture.getTextureId(), 0);
mOffscreenBuffer = framebuffer.get(0);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE) {
if(status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
Log.e("RENDERER","GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
if(status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
Log.e("RENDERER", "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
Log.e("RENDERER", "FRAMEBUFFER ERROR:"+status);
}
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
// called onFrameAvailable
public void getFramePixels() {
glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenBuffer);
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
Log.e(TAG, "FRAMEBUFFER STATUS:"+status);
}
glReadPixels(0, 0, width, height, GL_RGBA,
GL_UNSIGNED_BYTE,
intBuffer.clear());
StringBuilder str = new StringBuilder();
for(int i = 0; i < intBuffer.capacity(); i++)
{
str.append(intBuffer.get(););
}
Log.d(TAG, "IMAGE:" + str.toString());
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
If I display the texture on the screen, I am able to see it - so the texture not being actually bound to the camera is excluded.
Edit: there's a GL_INVALID_OPERATION happening at glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, getTextureId(), 0); for some reason.
From the docs:
GL_INVALID_OPERATION is generated if zero is bound to target.
GL_INVALID_OPERATION is generated if textarget and texture are not compatible.
My textureId is 1.

Read the docs more carefully. Your texture ID may be 1, but what you have currently bound to the target is likely actually 0. If you don't call glBindTexture(GL_TEXTURE_2D, mTangoCameraTexture.getTextureId()); then GL_TEXTURE_2D (the target) is whatever you set it to last, which I'm inclined to say is probably 0.
If you find you have performance issues surrounding glReadPixels() you should consider using it alongside a Pixel Buffer Object.

Related

Java + OpenGL: Texture Z-fighting in batch rendering

The main issue:
Good afternoon, everyone. I have such a question, when I use more than two textures in batch rendering, when using 2 textures (that is, my downloaded from disk), it starts glitching with the first texture (white), which in theory should not be because when the second texture is used from the texture slot, it becomes the main one for rendering. And this happens only in the perspective projection, everything is fine with the orthographic projection (most likely because it does not display the distance between objects and the Z-coordinate).
Here is a couple images of the issue:
Video
Google Drive
The whole problem is that I have a lot of code written and I think it will not make sense to throw off all of it. I will still show some pieces, but I would like you to express your assumption why this may happen. Maybe it's because I'm binding several texture slots at once. In general, I will be grateful to every advice or answer if it turns out.
Draw Sprite using batch rendering (Example)
public static void drawRectnagle(GameObject rect) {
var transform = rect.getComponent(Transform.class);
var spriteRenderer = rect.getComponent(SpriteRenderer.class);
// Begin new batch if in this batch not has room left.
if (batch.indexCount >= Batch.maxIndices)
newBatch();
int textureIndex = 0;
Vector2f[] textureCoords = batch.textureCoords;
Texture texture = null;
Vector4f color = null;
if(spriteRenderer != null) {
texture = spriteRenderer.texture;
color = spriteRenderer.color;
} else
color = new Vector4f(1, 1, 1, 1);
if(texture != null)
textureCoords = texture.getTextureCoords();
else
texture = batch.textures[0];
for (int i = 1; i < batch.textureIndex; i++) {
if (batch.textureIndex >= Batch.maxTextures)
newBatch();
// Equal texture by OpenGL ID's.
if (batch.textures[i].equals(texture)) {
textureIndex = i;
break;
}
}
if (textureIndex == 0.0f) {
textureIndex = batch.textureIndex;
batch.textures[batch.textureIndex] = texture;
batch.textureIndex++;
}
...
// Loading vertex data to batch.
...
}
Rendering batch after setting sprites data (Example)
private static void endBatch() {
if (batch.indexCount == 0)
return;
int sizeBytes = sizeof(Vertex.class); // NOTE: Size of Vertex class is currect here.
int size = batch.vertexIndex * sizeBytes;
batch.vertexBuffer.putData(batch.vertex, size, batch.vertexIndex, sizeBytes / 4);
// Bind each texture from slot.
for (int i = 0; i < batch.textureIndex; i++)
batch.textures[i].bind(i);
RenderEngine.EnableAlphaBlending();
RenderEngine.EnableDepthTesting();
glBindVertexArray(batch.vertexArray.get());
glDrawElements(GL_TRIANGLES, batch.vertexArray.getIndexBuffer().getCount(), GL_UNSIGNED_INT, 0);
RenderEngine.DisableAlphaBlending();
RenderEngine.DisableDepthTesting();
}
And if someone interest how my putData method works:
public void putData(Vertex[] vertex, int size, int index, int elementCount) {
//Convert all Vertex data to single float[] to pass as data in vertex buffer.
float[] data = ...
if(data != null) {
var pData = memAlloc(size).asFloatBuffer().put(data).flip();
glBindBuffer(GL_ARRAY_BUFFER, handle);
nglBufferData(GL_ARRAY_BUFFER, size, memAddress(pData), getOpenGLUsage(usage));
memFree(pData);
}
}
Fragment Shader
#version 450 core
layout (location = 0) out vec4 out_Pixel;
in vec3 position;
in vec4 color;
in vec2 textureCoord;
in float textureIndex;
uniform sampler2D u_Textures[32];
void main() {
vec4 texColour = vec4(1, 1, 1, 1);
texColour *= texture(u_Textures[int(textureIndex)], textureCoord);
vec4 finalColor = color * texColour;
if(finalColor.a < 0.1)
discard;
out_Pixel = finalColor;
}

Close objects are only partially rendered - LWJGL

I'm working on a LWJGL project and I'm experiencing a weird problem: close objects stop being fully rendered as I move slightly away. I'm not very expert in OpenGL so I can't figure out what is causing this.
Here two photos of what I'm talking about:
Pic1,
Pic2
And here's a photo to prove that the objects are fully loaded:
http://prntscr.com/r7joyc
Code used to load a texture
Code used to initialize the window
I think the error is somewhere here
#Override
public Texture loadTexture(String filename) {
try (MemoryStack stack = MemoryStack.stackPush()) {
//Height, width and colour channels are 1 byte each
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
IntBuffer channels = stack.mallocInt(1);
//Load image into the ByteBuffer
this.byteBuffer = stbi_load(filename, w, h, channels, 4);
if (this.byteBuffer == null) {
throw new FileNotFoundException("Texture file [" + filename + "] not loaded. Reason: " + stbi_failure_reason());
}
//Get width and height of image
this.width = w.get();
this.height = h.get();
int textureID = this.generateTexture();
this.generateMipMap();
this.clean();
return new Texture(textureID, this.width, this.height);
} catch (Exception e) {
logger.error(e.getMessage());
e.printStackTrace();
return null;
}
}
//For scaled textures
private void generateMipMap() {
glGenerateMipmap(GL_TEXTURE_2D);
}
private int generateTexture() {
int textureId = glGenTextures();
// Bind the texture
glBindTexture(GL_TEXTURE_2D, textureId);
//Tell OpenGL how to unpack RGBA. 1 byte for pixel
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/*Args:
1. Type of texture;
2. Number of colour components in the texture;
3. Colour components in texture;
4. Texture width;
5. Texture height;
6. Texture border size;
7. Format of the pixel data (RGBA);
8. Each pixel is represented by an unsigned int;
9. Data to load is stored in a ByteBuffer
*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this.width, this.height,
0, GL_RGBA, GL_UNSIGNED_BYTE, this.byteBuffer);
return textureId;
}
private void clean() {
//Free ByteBuffer
stbi_image_free(this.byteBuffer);
}
Or here
public void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();
// Initialize GLFW. Most GLFW functions will not work before doing this.
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // the window will be resizable
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
boolean maximized = false;
// If no size has been specified set it to maximized state
if (width == 0 || height == 0) {
// Set up a fixed width and height so window initialization does not fail
width = 100;
height = 100;
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
maximized = true;
}
windowHandle = glfwCreateWindow(width, height, title, NULL, NULL);
// Create the window
if (windowHandle == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
}
logger.trace("Window handle: " + windowHandle);
// Setup resize callback
glfwSetFramebufferSizeCallback(windowHandle, (window, width, height) -> {
this.width = width;
this.height = height;
this.setResized(true);
});
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(windowHandle, (window, key, scancode, action, mods) -> {
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
}
});
if (maximized) {
glfwMaximizeWindow(windowHandle);
} else {
// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center our window
glfwSetWindowPos(
windowHandle,
(vidmode.width() - width) / 2,
(vidmode.height() - height) / 2
);
}
// Make the OpenGL context current
glfwMakeContextCurrent(windowHandle);
if (isvSync()) {
// Enable v-sync
glfwSwapInterval(1);
}
// Make the window visible
glfwShowWindow(windowHandle);
GL.createCapabilities();
// Set the clear color
setClearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);
glEnable(GL_DEPTH_TEST);
// Support for transparencies
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
if(debug){
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
}
}
This solved my problem
First render your skybox, then clear the depth bit after rendering the skybox, and finally render everything else. That way the depth of the skybox won't affect the scene.

Framebuffers can't store floating point numbers

I've tried to implement deferred shading but the gbuffer can't store any floating point numbers. The edges from the lighting is VERY rough since the framebuffer can't store negative components for the normals eventhough i passed in the correct internal format and data type.
Example picture of the rough edges
Texture generation:
public TextureResource(int width, int height, int filter, int internalFormat, int format, boolean clamp, int dataType, ByteBuffer data) {
id = glGenTextures();
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, dataType, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
if(clamp) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
Framebuffer generation:
this.width = width;
this.height = height;
this.attachments = attachments;
boolean hasDepth = false;
IntBuffer drawBuffers = Util.createIntBuffer(attachments.length);
assert(attachments.length <= MAX_ATTACHMENTS);
framebuffer = glGenFramebuffers();
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
for(int i = 0; i < attachments.length; i++) {
if(attachments[i].getAttachmentType() == GL_DEPTH_ATTACHMENT) {
drawBuffers.put(GL_NONE);
hasDepth = true;
} else {
drawBuffers.put(attachments[i].getAttachmentType());
}
if(attachments[i].getAttachmentType() == GL_NONE) {
continue;
}
attachments[i].createTexture(width, height);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i].getAttachmentType(), GL_TEXTURE_2D, attachments[i].getTexture().getId(), 0);
}
if(!hasDepth) {
renderbuffer = glGenRenderbuffers();
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
}
drawBuffers.flip();
glDrawBuffers(drawBuffers);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
System.err.println("Framebuffer creation failed!");
System.exit(1);
}
GBuffer:
super(width, height, new FramebufferAttachment(GL_COLOR_ATTACHMENT1, GL_NEAREST, GL_RGB32F, GL_RGB, false, GL_FLOAT),
new FramebufferAttachment(GL_COLOR_ATTACHMENT0, GL_NEAREST, GL_RGB32F, GL_RGB, false, GL_FLOAT),
new FramebufferAttachment(GL_COLOR_ATTACHMENT2, GL_NEAREST, GL_RGB, GL_RGB, false, GL_UNSIGNED_BYTE));
Geometry pass fragment shader:
#version 330 core
in vec3 worldPos0;
in vec2 texCoord0;
in vec3 normal0;
layout (location = 0) out vec3 gWorldPos;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec3 gColor;
uniform sampler2D diffuse;
void main() {
gWorldPos = worldPos0;
gNormal = normalize(normal0);
gColor = texture(diffuse, texCoord0).xyz;
}
It's because it is 3.3 core. OpenGL standard somewhat contradicts itself on the matter of what format are renderable, some implementations actually support RGBxF formats. OpenGL 4.4 specs declare them renderable.
Ifit is really needed, I think is it possible to map integer values to floating point. Ofc you still have limited amount of values, but you can implement negative and fraction values, while having limited range

how to remove a color (make it transparent) taking the color from a pixel in OpenGL

What I want to do is this, imagine I have a little tile (32x32) with the Sun inside, that is a yellow circle with black background.
I want to draw that Sun in the sky (light blue). Obviously the black border will ruin my composition. I have to make OpenGL delete that black color.
In photoshop I would select with the magic tool all the black pixels and then remove them saving the new file with alpha channel.
But this can be too long to do if you have millions of images. I have to handle this issue at runtime.
I was looking for the glStencilMask method, but that will work if you actually have a texture to use as mask.
I found an example for C# that talks about taking the 24bit image and transform to 32bit with alpha channel, this sound to me good, but maybe in matter of time consuming and resource spending is too much especially if the number of tile is high (about 30x20 tiles at 60fps)
The thing is that this is difficult to reach, and the one who reach this goal is not going to tell anybody...
Actually the code to draw the tile is this, that will cut, translate, rotate and all the stuff that are needed.
GL11.glPushMatrix();
// bind to the appropriate texture for this sprite
this.texture.bind();
// translate to the right location and prepare to draw
GL11.glColor3f(1, 1, 1);
GL11.glTranslated(x + ((32 - this.texture.getImageWidth()) / 2) + (this.texture.getImageWidth() / 2), y + ((32 - this.texture.getImageHeight()) / 2)
+ (this.texture.getImageHeight() / 2), 0);
// System.out.println(this.angle);
GL11.glRotated(this.angle, 0, 0, 1);
GL11.glTranslated(-this.texture.getImageWidth() / 2, -this.texture.getImageHeight() / 2, 0);
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(0, this.texture.getHeight());
GL11.glVertex2f(0, this.texture.getImageHeight());
GL11.glTexCoord2f(this.texture.getWidth(), this.texture.getHeight());
GL11.glVertex2f(this.texture.getImageWidth(), this.texture.getImageHeight());
GL11.glTexCoord2f(this.texture.getWidth(), 0);
GL11.glVertex2f(this.texture.getImageWidth(), 0);
}
GL11.glEnd();
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
texture.bind is this:
public void bind() {
GL11.glBindTexture(this.target, this.textureID);
}
With image that contain a transparent layer all is perfect.
Once I have find out how to remove that specific color I wish to remove the color according to the upper-left pixel and that will be done with glReadPixels()
here is the loader:
public Texture getTexture(String resourceName, int target, int dstPixelFormat, int minFilter, int magFilter) throws IOException {
int srcPixelFormat = 0;
// create the texture ID for this texture
int textureID = this.createTextureID();
Texture texture = new Texture(target, textureID);
// bind this texture
GL11.glBindTexture(target, textureID);
BufferedImage bufferedImage = this.loadImage(resourceName);
texture.setWidth(bufferedImage.getWidth());
texture.setHeight(bufferedImage.getHeight());
if (bufferedImage.getColorModel().hasAlpha()) {
srcPixelFormat = GL11.GL_RGBA;
} else {
srcPixelFormat = GL11.GL_RGB;
}
// convert that image into a byte buffer of texture data
ByteBuffer textureBuffer = this.convertImageData(bufferedImage, texture);
if (target == GL11.GL_TEXTURE_2D) {
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
}
// produce a texture from the byte buffer
GL11.glTexImage2D(target, 0, dstPixelFormat, this.get2Fold(bufferedImage.getWidth()), this.get2Fold(bufferedImage.getHeight()), 0, srcPixelFormat,
GL11.GL_UNSIGNED_BYTE, textureBuffer);
return texture;
}
Actually I've created a solution to the problem, so I've created a method that I am going to post here on SO to knowledge for future people.
/**
* Sets the specified colour, or the color taken from the top-left pixel, to transparent
*
* #param image
* The image to process (<code>BufferedImage</code>)
* #param cornerTransparency
* If true the method will take the top-left pixel's colour and make it transparent in the image
* #param transCol
* If <code>cornerTransparency</code> is false, this is the color that will be set to transparent.
* #return The loaded buffered image
* #throws IOException
* Indicates a failure to find a resource
*/
private BufferedImage loadImage(BufferedImage image, boolean cornerTransparency, int transCol) throws IOException {
if(image == null){
throw new IllegalArgumentException();
}
int firstPixel = bufferedImage.getRGB(0, 0);
BufferedImage bff = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < bufferedImage.getHeight(); ++y) {
for (int x = 0; x < bufferedImage.getWidth(); ++x) {
int argb = bufferedImage.getRGB(x, y);
if (cornerTransparency) {
if (argb == firstPixel) {//we are certain that they are of the same type (RGB,ARGB etc)
bff.setRGB(x, y, 0); //black with alpha = 0
} else {
bff.setRGB(x, y, argb);
}
} else {
if ((argb & 0xFF000000) == (transCol & 0xFF000000)) {//not sure if are of the same type, I remove the alpha data.
bff.setRGB(x, y, 0); //black with alpha = 0
} else {
bff.setRGB(x, y, argb);
}
}
}
}
return bff;
} else {
return bufferedImage;
}

Display image in JOGL

I'm currently working on an assignment where I need to create a game in JOGL, it's going pretty well, but I've run into a problem:
I want to create a menu function that can be accessed by pressing ESC ingame, when ESC is pressed the display function needs to stop displaying the game and start displaying the menu. The menu consists of a background image with some text overlay.
This is how I tried to implement the menu function, but I haven't managed to let it show anything else than the clear color:
public class OptionsMenu
{
public void display(GL gl) {
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(0, 300, 300, 0, 0, 1);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glDisable(GL.GL_DEPTH_TEST);
gl.glClearColor(1f, 0.5f, 0.5f, 0.5f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glBlendFunc (GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable (GL.GL_BLEND);
BufferedImage bufferedImage = null;
int w = 0;
int h = 0;
try {
bufferedImage = ImageIO.read(OptionsMenu.class.getResource("menuBackground.jpg")); //The menu background
w = ceilingPow2(bufferedImage.getWidth());
h = ceilingPow2(bufferedImage.getHeight());
} catch (IOException e) {
e.printStackTrace();
}
WritableRaster raster =
Raster.createInterleavedRaster (DataBuffer.TYPE_BYTE,
w,
h,
4,
null);
ComponentColorModel colorModel=
new ComponentColorModel (ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] {8,8,8,8},
true,
false,
ComponentColorModel.TRANSLUCENT,
DataBuffer.TYPE_BYTE);
BufferedImage img =
new BufferedImage (colorModel,
raster,
false,
null);
Graphics2D g = img.createGraphics();
g.drawImage(bufferedImage, null, null);
DataBufferByte imgBuf =
(DataBufferByte)raster.getDataBuffer();
byte[] imgRGBA = imgBuf.getData();
ByteBuffer bb = ByteBuffer.wrap(imgRGBA);
bb.position(0);
bb.mark();
gl.glBindTexture(GL.GL_TEXTURE_2D, 13);
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
gl.glTexImage2D (GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, w, h, 0, GL.GL_RGBA,
GL.GL_UNSIGNED_BYTE, bb);
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBindTexture (GL.GL_TEXTURE_2D, 13);
gl.glBegin (GL.GL_POLYGON);
gl.glTexCoord2d (0, 0);
gl.glVertex2d (0, 0);
gl.glTexCoord2d(1,0);
gl.glVertex2d (w, 0);
gl.glTexCoord2d(1,1);
gl.glVertex2d (w, h);
gl.glTexCoord2d(0,1);
gl.glVertex2d (0, h);
gl.glEnd ();
gl.glFlush();
}
private static int ceilingPow2(int n) {
int pow2 = 1;
while (n > pow2) {
pow2 = pow2<<1;
}
return pow2;
}
}
This code is based of this tutorial: http://wiki.tankaar.com/index.php?title=Displaying_an_Image_in_JOGL_(Part_1)
I'm calling upon the OptionsMenu like so:
public void display(GLAutoDrawable drawable)
{
GL gl = drawable.getGL();
GLU glu = new GLU();
if(state.equals("optionsMenu"))
{
if(menu == null)
menu = new OptionsMenu;
menu.display(gl);
}
else
{
// Calculating time since last frame.
Calendar now = Calendar.getInstance();
long currentTime = now.getTimeInMillis();
int deltaTime = (int)(currentTime - previousTime);
previousTime = currentTime;
// Update any movement since last frame.
updateMovement(deltaTime);
updateCamera();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
gl.glLoadIdentity();
glu.gluLookAt( camera.getLocationX(), camera.getLocationY(), camera.getLocationZ(),
camera.getVrpX(), camera.getVrpY(), camera.getVrpZ(),
camera.getVuvX(), camera.getVuvY(), camera.getVuvZ() );
// Display all the visible objects of MazeRunner.
for( Iterator<VisibleObject> it = visibleObjects.iterator(); it.hasNext(); ) {
it.next().display(gl);
}
gl.glLoadIdentity();
gl.glFlush();
}
}
It doesn't throw any errors, it just won't display the image. It does however show the clear color gl.glClearColor(1f, 0.5f, 0.5f, 0.5f); defined in the display function of the OptionsMenu
I'm pretty much stumped and I have no idea how I'm going to fix this.
Sorry for the long post, but I'd be REALLY grateful if someone would help me.
I guess clear color buffers gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
should be placed at the begining of display method of OptionsMenu.
I have few advices for example posted code above:
Change scope of the GLU glu = new GLU();, because glu assigned each time when opengl display callback method called.
Also move gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); right before if statement, and do not use every objects display method (e.g OptionsMenu.display()). Try keep it single.
Use TextureIO to upload texture, and if its possible just upload it once then use that texture in your display method. Texture loading process has great overhead.

Categories