Bind GLES texture to GL_TEXTURE_2D from GL_TEXTURE_EXTERNAL_OES - android

I have a texture, bound to GL_TEXTURE_EXTERNAL_OES target
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
How can rebind it to GL_TEXTURE_2D target?
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); provides error

You can't. The texture target is a fundamental part of the texture object. If you have an external texture, you cannot treat it like a GL_TEXTURE_2D. At all.
This means if you want to bind it, you must bind it as a GL_TEXTURE_EXTERNAL_OES texture. If you want to use it in a sampler, that sampler must be of type samplerExternalOES rather than sampler2D (and your shader must enable the appropriate extension). And so forth.

Related

Android How to generate mipmap for GL_TEXTURE_EXTERNAL_OES

When i render the cameraTexture to a low resolution SurfaceView, it looks pixelated.
Seems i need to generate mipmap for the camera texture, but it doesn't work this way.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glGenTextures(1, glTextures, 0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, glTextures[0]);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
mInputSurfaceTexture = new SurfaceTexture(inputTexture);
mInputSurfaceTexture.setDefaultBufferSize(CCamera.SIZE.getWidth(), CCamera.SIZE.getHeight());
mInputSurfaceTexture.setOnFrameAvailableListener(new CameraFrameListener(), mGLHandler);
mInputSurface = new Surface(mInputSurfaceTexture);
# feed mInputSurface to camera service.
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
surfaceTexture.updateTexImage();
GLES20.glGenerateMipmap(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
//GLES11Ext.glGenerateMipmapOES(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
}
BTW, that is the different of :
GLES11Ext.glGenerateMipmapOES
GLES20.glGenerateMipmap
You can't, at least not directly.
Implement an offscreen pass that converts the YUV to RGB to write an RGB image, and then mipmap that. If you know you only need the low resolution version, that YUV to RGB pass could also implement the initial 2:1 downsample to minimize the memory bandwidth overheads.

How to change texture.png after 3d.obj was placed in the surface using ARCORE?

I've four types of texture.png for one 3d.obj file. How to change texture.png after 3d.obj was placed in the surface, like color changing functionality for ARCORE?
Does anyone have any idea?
You can change the texture of the object. Assuming you are looking at the hello_ar_java sample, you can add a method to ObjectRenderer:
public void setTextureOnGLThread(Bitmap textureBitmap) {
// Bind the texture name already allocated.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
// Set the filtering for handling different sizes to render.
GLES20.glTexParameteri(
GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
// Copy the bitmap contents into the texture buffer.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, textureBitmap, 0);
// Generate the mip map for the different sizes.
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
// Unbind the texture.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}
You need to call this from the GL thread, for example from onDrawFrame().

Allow for Multiple-Pass Renders in GLSurfaceView Renderer with SurfaceTexture

I am displaying a video on a GLSurfaceView with a custom renderer that requires that multiple shaders be applied in succession. Currently, it is working successfully with one shader, though I am not sure how to extend the rendering pipeline to apply multiple shaders in succession.
I know that there are some examples concerning applying multiple shaders (using FrameBuffers and RenderBuffers), but I have not found any that deal with an image passed in through a SurfaceTexture.
There is a specific concern I would like to address:
A SurfaceTexture must be bound to a GL_TEXTURE_EXTERNAL_OES texture. On the other hand, a FrameBuffer cannot be bound to a GL_TEXTURE_EXTERNAL_OES texture (typically a GL_TEXTURE_2D is used), so is it even possible to use a FrameBuffer for a multi-pass render when the input texture is of a different format than the output? If not, what are the other options for performing a multi-pass render?
Below is some relevant code in the onSurfaceCreated function of the renderer I am trying to extend to perform multiple passes::
GLES20.glGenTextures(1, this.textureID, 0);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, this.textureID[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
this.surfaceTexture = new SurfaceTexture(this.textureID[0]);
Below is some relevant code in the onDrawFrame function of that renderer:
synchronized (this) {
if (this.updateSurface) {
this.surfaceTexture.updateTexImage();
this.surfaceTexture.getTransformMatrix(this.stMatrix);
this.updateSurface = false;
}
}
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, this.textureID[0]);
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
//apply shader here and call glDrawArrays() at end
One way to approach this would be to use a SurfaceHolder rather than a SurfaceTexture.
From there, you can then get the Surface being held by the SurfaceHolder.
Then you can get the underlying Canvas being drawn to.
Note: Per this answer, you will need to use setBitmap(Bitmap canvas_bitmap) to specify the Bitmap being drawn into.
All the texture setup and parameter stuff will still need to be done basically the way you showed in you question.
GLES20.glGenTextures(1, this.textureID, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.textureID[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
Then dump the bitmap into a texture using:
GLUtils.texImage2D( GLES20.GL_TEXTURE_2D, 0, canvas_bitmap, 0 );

same SurfaceTexture for 2 views

Is it possible to use same surfacetexture for 2 views? If so, how?
I use mediaplayer to play video and I want to play same video on 2 different views at the same time.
I tried to create SurfaceTexture and then set this surface texture to both views but it doesn't work.
public int createTextureObject() {
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
int texId = textures[0];
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texId);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
return texId;
}
SurfaceTexture st = new SurfaceTexture(createTextureObject());
textureView1.setSurfaceTexture(st);
textureView2.setSurfaceTexture(st);
mMediaPlayer.setSurface(new Surface(st));
It randomly works on one or another view but not on both at the same time.
I don't believe shared SurfaceTextures are supported by TextureView. I don't know that there's anything that would prevent it from being possible, but the onFrameAvailable() callback can only notify one object.
(You might be able to jury-rig something where you manually invoke the callback in the second instance from the first, but that seems like asking for trouble.)
An approach that will work is to create the SurfaceTexture as you are doing now, and send the video frames to it, but provide an onFrameAvailable() listener that renders the video frame to the two TextureViews using OpenGL ES.
Various examples of this can be found in Grafika, e.g. "continuous capture" receives Camera input on a SurfaceTexture and then renders it twice (once to the display, once to a video encoder).

OpenGL ES2.0 glitches on framebuffer texture

I have a problem with the rendering to texture in my Android based game (OpenGl ES2.0). I wasn't aware of the issue as on most devices this problem doesn't exists and everything is drawn just fine.
Regarding the screenshot attached below, the red bar on the left is drawn on the main framebuffer and because of that it is properly displayed. Everything else is rendered on off-screen texture which is then rendered on the main framebuffer.
I'm attaching the screenshot made on Samsung Galaxy Y S5360 (I'm not aware if this issue occur on other devices) as well as the code responsible for off-screen framebuffer/texture creation:
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[i]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebuffer[i]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texture[i], 0);
if(GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) {
// ...
If I'm not mistaken, Samsung Galaxy Y S5360 has only OpenGL ES-CM 1.1 See http://geekprison.com/2163-samsung-galaxy-y-s5360-pricespecification-announced-for-india/

Categories

Resources