I am using following method to create OpenGL ES texture on android.
private int createTexture(int width, int height, int i) {
int[] mTextureHandles = new int[1];
GLES20.glGenTextures(1, mTextureHandles, 0);
int textureID = mTextureHandles[0];
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
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_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
return textureID;
}
Then uploading a bitmap to this texture and simply rendering it using GLSurfaceView's Renderer.
Most of the times it is working as expected,
But randomly the texture is displayed like this. (here GL_TEXTURE_WRAP_S mode is GLES20.GL_CLAMP_TO_EDGE
After changing wrap mode.
If GL_TEXTURE_WRAP_S = GLES20.GL_REPEAT then (again randomly) texture is displayed like this(notice the color change).
I have already tried using power of 2 texture.
Code for vertex buffer
private FloatBuffer createVertexBuffer(RectF glCoords) {
// RectF glCoords contains gl vertices.
// current Rect read from Logcat.
// left = -0.5833333, top = 0.5, right = 0.5833334, bottom = -0.5
float[] vertices = new float[]{glCoords.left, glCoords.top, 0, 1, // V1 - top left
glCoords.left, glCoords.bottom, 0, 1, // V2 - bottom left
glCoords.right, glCoords.bottom, 0, 1, // V3 - bottom right
glCoords.right, glCoords.top, 0, 1 // V4 - top right
};
FloatBuffer vBuffer = ByteBuffer.allocateDirect(vertices.length * bytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
vBuffer.put(vertices);
vBuffer.position(0);
return vBuffer;
}
IndicesBuffer is not used as I am using Triangle-Fan to render triangles.
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);
It would be really helpful if someone can point out as to what could be causing this
Your geometry seems to be a 4-vertex rectangle (quad), but the code wants to draw a fan with 6 vertices - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);
Those extra 2 vertices aren't initialized, not specified in the vertex array. OpenGL will read beyond the defined part of the array. The results would be random, and I'd even expect crashes.
Replace 6 with 4 in glDrawArrays() call, this should fix the problem.
Related
I am writing an app utilizing CameraX to capture the camera feed, OpenCV to modify the frames and the OpenGL to render them on a GLSurfaceView.
My current approach was to render the original frames from CameraX, construct a pixel buffer, an OpenCV Mat, use glReadPixels to copy the pixel buffer (ByteBuffer) into the Mat, then process it, write the pixel buffer from Mat back to the pixel buffer and then render it onto the texture with glTexSubImage2D.
The problem is, CameraX enables me to access the frame data via GL_TEXTURE_EXTERNAL_OES, which - as per OpenGL's documentation - does not allow for glTexSubImage2D to modify the texture and my current approach, using the code below, does not work and continously throws W/OpenGLRenderer: [SurfaceTexture-1-25873-0] bindTextureImage: clearing GL error: 0x500, which is expected as says the documentation. Is there an alternative way to copy the buffer into GL_TEXTURE_EXTERNAL_OES after OpenCV processing? Another thing I can think of is to copy the texture into GL_TEXTURE_2D and then use glTexSubImage2D, although I have no idea how to do that. Maybe someone knows another approach that would allow me to achieve the goal?
My code:
public void onDrawFrame(GL10 gl) {
GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT );
if(this.resolutionSet) {
surfaceTexture.updateTexImage();
GLES20.glUseProgram(hProgram);
int ph = GLES20.glGetAttribLocation(hProgram, "vPosition");
int tch = GLES20.glGetAttribLocation(hProgram, "vTexCoord");
int th = GLES20.glGetUniformLocation(hProgram, "sTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, hTex[0]);
GLES20.glUniform1i(th, 0);
GLES20.glVertexAttribPointer(ph, 2, GLES20.GL_FLOAT, false, 4 * 2, pVertex);
GLES20.glVertexAttribPointer(tch, 2, GLES20.GL_FLOAT, false, 4 * 2, pTexCoord);
GLES20.glEnableVertexAttribArray(ph);
GLES20.glEnableVertexAttribArray(tch);
GLES20.glReadPixels(0, 0, this.img.cols(), this.img.rows(), GL_RGBA, GL_UNSIGNED_BYTE, this.imgBuff);
img.put(0, 0, this.imgBuff.array());
Log.d(LOG_TAG, img.toString());
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2BGRA);
Imgproc.cvtColor(img, img, Imgproc.COLOR_BGRA2GRAY);
this.imgBuff.clear();
img.get(0, 0, this.imgBuff.array());
GLES20.glTexImage2D(GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
GLES20.glTexSubImage2D(GL_TEXTURE_EXTERNAL_OES, 0, 0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, this.imgBuff);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
GLES20.glFlush();
}
and the code initializing texture:
hTex = new int[1];
GLES20.glGenTextures ( 1, hTex, 0 );
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, hTex[0]);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
Given you are replacing the entire image and uploading "normal" RGBA data from the application, why does this need to be a GL_TEXTURE_EXTERNAL_OES type at all? Just use a normal GL_TEXTURE_2D.
I am new to OpenGL, work on Android. Found good code example in Web with possibility to record everything. But I found one big problem: depth test doesn't work, so in my models all faces that opposite to camera are lighted even if they are behind another faces:
I think some mistakes could be in this part of code:
/**
* Prepares the off-screen framebuffer.
*/
private void prepareFramebuffer(int width, int height) {
GlUtil.checkGlError("prepareFramebuffer start");
int[] values = new int[1];
// Create a texture object and bind it. This will be the color buffer.
GLES20.glGenTextures(1, values, 0);
GlUtil.checkGlError("glGenTextures");
mOffscreenTexture = values[0]; // expected > 0
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mOffscreenTexture);
GlUtil.checkGlError("glBindTexture " + mOffscreenTexture);
// Create texture storage.
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
// Set parameters. We're probably using non-power-of-two dimensions, so
// some values may not be available for use.
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
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);
GlUtil.checkGlError("glTexParameter");
// Create framebuffer object and bind it.
GLES20.glGenFramebuffers(1, values, 0);
GlUtil.checkGlError("glGenFramebuffers");
mFramebuffer = values[0]; // expected > 0
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebuffer);
GlUtil.checkGlError("glBindFramebuffer " + mFramebuffer);
// Create a depth buffer and bind it.
GLES20.glGenRenderbuffers(1, values, 0);
GlUtil.checkGlError("glGenRenderbuffers");
mDepthBuffer = values[0]; // expected > 0
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, mDepthBuffer);
GlUtil.checkGlError("glBindRenderbuffer " + mDepthBuffer);
// Allocate storage for the depth buffer.
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
width, height);
GlUtil.checkGlError("glRenderbufferStorage");
// Attach the depth buffer and the texture (color buffer) to the framebuffer object.
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
GLES20.GL_RENDERBUFFER, mDepthBuffer);
GlUtil.checkGlError("glFramebufferRenderbuffer");
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, mOffscreenTexture, 0);
GlUtil.checkGlError("glFramebufferTexture2D");
// See if GLES is happy with all this.
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
// throw new RuntimeException("Framebuffer not complete, status=" + status);
}
// Switch back to the default framebuffer.
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GlUtil.checkGlError("prepareFramebuffer done");
}
Another important things that I have already done:
/**
* Prepares window surface and GL state.
*/
private void prepareGl(Surface surface) {
Log.d(TAG, "prepareGl");
EglCore.logCurrent("before creating");
GlUtil.checkGlError("debug");
if (mWindowSurface == null)
mWindowSurface = new WindowSurface(mEglCore, surface, false);
mWindowSurface.makeCurrent();
EglCore.logCurrent("after creation");
glClearColor(0f, 0f, 0f, 1f); //glClearColor(0.15f, 0.15f, 0.15f, 1f);
GlUtil.checkGlError("debug");
glEnable(GL_DEPTH_TEST);
GlUtil.checkGlError("debug");
glEnable(GL_CULL_FACE);
GlUtil.checkGlError("debug");
glCullFace(GL_BACK);
GlUtil.checkGlError("debug");
glShadeModel(GL_SMOOTH);
GlUtil.checkGlError("debug");
glEnable(GL_BLEND);
GlUtil.checkGlError("debug");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
What am I doing wrong? Where can be the mistake?
Add onDraw code:
private void draw() {
GlUtil.checkGlError("draw start");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_LESS);
if (leftEye != null) {
resetMatrices();
setModelViewMatrix();
translateMEyes();
eyeTextureProgram.useProgram();
eyeTextureProgram.setViewAndTexture(modelViewProjectionMatrix, textureEye);
setProgramParams(eyeTextureProgram, textureEye);
leftEye.bindData(eyeTextureProgram);
leftEye.draw();
}
if (rightEye != null) {
rightEye.bindData(eyeTextureProgram);
rightEye.draw();
}
glDepthFunc(GL_LEQUAL);
resetMatrices();
setModelViewMatrix();
setProgramParams(faceTextureProgram, textureFace);
headBase.bindData(faceTextureProgram);
headBase.draw();
GlUtil.checkGlError("draw done");
}
Set the clearing value of the depth buffer to 1.0. Clearing value of the depth buffer should be the max value of the depth range which by default is 0.0 - 1.0.
glClearDepth(1.0)
Also, ensure that you clear both the depth and color buffer before your drawing.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
I want use OpenGL ES to draw a frame animation, so I use glTexSubImage2D to update the texture.
This function initializes the texture:
private void initTexture()
{
textures=new int[1];
GLES20.glGenTextures(1,textures,0);
//Bitmap bitmap= BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/xiaobizi/xiaobizi_0001.png");
Bitmap bitmap= BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/aa.png");
ratio=(float)bitmap.getHeight()/(float)bitmap.getWidth();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[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);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
this function to save&remove Bitmap:
mTextureMap.remove(mPathList.get(messageTag));
mTextureMap.put(mPathList.get(saveCount),BitmapFactory.decodeFile(mPathList.get(saveCount)));
private void drawMagic()
{
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE,GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glUseProgram(programMagic);
int mPositionHandleFace = GLES20.glGetAttribLocation(programMagic, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandleFace);
GLES20.glVertexAttribPointer(mPositionHandleFace, 2, GLES20.GL_FLOAT, false, 0, 0);
int mTexCoordLocFace = GLES20.glGetAttribLocation(programMagic, "a_texCoord" );
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray ( mTexCoordLocFace );
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer(mTexCoordLocFace, 2, GLES20.GL_FLOAT, false, 0, 0);
// Get handle to shape's transformation matrix
int mTransHandle = GLES20.glGetUniformLocation(programMagic, "transMatrix");
int mScaleHandle=GLES20.glGetUniformLocation(programMagic,"scaleMatrix");
int mRotateXHandle=GLES20.glGetUniformLocation(programMagic,"rotateXMatrix");
int mRotateZHandle=GLES20.glGetUniformLocation(programMagic,"rotateZMatrix");
int mRotateYHandle=GLES20.glGetUniformLocation(programMagic,"rotateYMatrix");
//control matrix
GLES20.glUniformMatrix4fv(mTransHandle,1,false,transMatrix,0);
GLES20.glUniformMatrix4fv(mScaleHandle,1,false,scaleMatrix,0);
GLES20.glUniformMatrix4fv(mRotateXHandle,1,false,rotateXMatrix,0);
GLES20.glUniformMatrix4fv(mRotateZHandle,1,false,rotateZMatrix,0);
GLES20.glUniformMatrix4fv(mRotateYHandle,1,false,rotateYMatrix,0);
int mtrxhandleFace = GLES20.glGetUniformLocation(programMagic, "uMVPMatrix");
// Apply the projection and view transformation
//GLES20.glUniformMatrix4fv(mtrxhandleFace, 1, false, mGLTextureTransformMatrix, 0);
GLES20.glUniformMatrix4fv(mtrxhandleFace, 1, false, mSecondTransFormMatrix, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[0]);
if(i>=mTotalCount)
{
i=i-mTotalCount;
}
// update texture
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D,0,0,0,mTextureMap.get(mPathList.get(i)));
int mSamplerLocFace = GLES20.glGetUniformLocation (programMagic, "s_texture" );
// Set the sampler texture unit to 0, where we have saved the texture.
GLES20.glUniform1i ( mSamplerLocFace, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandleFace);
GLES20.glDisableVertexAttribArray(mTexCoordLocFace);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);
mDecodeHandler.sendEmptyMessage(i);
i++;
}
this is my drawFrame function.
In initTexture function if the bitmap belongs to the Frame Animation, texSubImage2D works,the texture always updating, but if i pass a bitmap that does't belongs to the Frame Animation , the function texSubImage2D does't work. In that case, the texture always was the bitmap that i passed in function initTexture didn't update.
If i called the function when opengl was dawing, the texture was black,but its shapes can be displayed properly, just the background was black.
I am searching for a long time on net. But no use. Please help or try to give some ideas how to fix this.thank u.
I develop video app on Android and use OpenGL for render and filtering video from camera via shaders. One of my shaders use two textures - one is live frame from camera and another is the previous render pass result. So I need to render picture twice - to screen for preview and to separate Texture for next render pass. To achieve it I use Frame Buffer object. Here is my code:
For init frame buffer:
private void initPredrawBuffer() {
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
prevBuffer = new int[1];
GLES20.glGenFramebuffers(1, prevBuffer, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]);
prevTexture = new int[1];
GLES20.glGenTextures(1, prevTexture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
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.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mFrameWidth, mFrameHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, prevTexture[0], 0);
int[] depthRenderbuffers = new int[1];
GLES20.glGenRenderbuffers(1, depthRenderbuffers, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mFrameWidth, mFrameHeight);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]);
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
throw new RuntimeException("Incomplete buffer");
}
}
and for render:
private void draw(boolean offScreen, float[] mvpMatrix, FloatBuffer vertexBuffer, int firstVertex,
int vertexCount, int coordsPerVertex, int vertexStride,
float[] texMatrix, FloatBuffer texBuffer, int textureId, int texStride) {
GlUtil.checkGlError("draw start");
if (offScreen)
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]);
else
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
// Select the program.
GLES20.glUseProgram(firstFrame && firstFrameProgram > 0 ? firstFrameProgram : mProgramHandle);
GlUtil.checkGlError("glUseProgram");
// Set the texture.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
// Copy the model / view / projection matrix over.
GLES20.glUniformMatrix4fv(muMVPMatrixLoc, 1, false, mvpMatrix, 0);
GlUtil.checkGlError("glUniformMatrix4fv");
// Copy the texture transformation matrix over.
GLES20.glUniformMatrix4fv(muTexMatrixLoc, 1, false, texMatrix, 0);
GlUtil.checkGlError("glUniformMatrix4fv");
// Enable the "aPosition" vertex attribute.
GLES20.glEnableVertexAttribArray(maPositionLoc);
GlUtil.checkGlError("glEnableVertexAttribArray");
// Connect vertexBuffer to "aPosition".
GLES20.glVertexAttribPointer(maPositionLoc, coordsPerVertex,
GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
GlUtil.checkGlError("glVertexAttribPointer");
// Enable the "aTextureCoord" vertex attribute.
GLES20.glEnableVertexAttribArray(maTextureCoordLoc);
GlUtil.checkGlError("glEnableVertexAttribArray");
// Connect texBuffer to "aTextureCoord".
GLES20.glVertexAttribPointer(maTextureCoordLoc, 2,
GLES20.GL_FLOAT, false, texStride, texBuffer);
GlUtil.checkGlError("glVertexAttribPointer");
// Setting Light Trails filter params
if (mProgramType == ProgramType.TEXTURE_LIGHT_TRAILS && !firstFrame) {
GLES20.glUniform1i(muTextureNew, 0);
GlUtil.checkGlError("glUniform1i muTextureNew");
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GlUtil.checkGlError("temp glActiveTexture");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]);
GlUtil.checkGlError("temp glBindTexture");
GLES20.glUniform1i(muTexturePrev, 1);
GlUtil.checkGlError("glUniform1i muTexturePrev");
GLES20.glUniform1f(muLightTrailsExposure, lightTrailsKernel[0]);
GlUtil.checkGlError("glUniform1f muLightTrailsExposure");
GLES20.glUniform1f(muLightTrailsEcho, lightTrailsKernel[1]);
GlUtil.checkGlError("glUniform1f muLightTrailsEcho");
GLES20.glUniform1f(muLightTrailsLimit, lightTrailsKernel[2]);
GlUtil.checkGlError("glUniform1f muLightTrailsLimit");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GlUtil.checkGlError("temp glActiveTexture");
}
// Draw the rect.
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, firstVertex, vertexCount);
GlUtil.checkGlError("glDrawArrays");
GLES20.glFinish();
}
The problem is that render to frame buffer not working, and glReadPixels always return an empty array. Render to screen works fine.
I want to load more than one textures in OpenGL and use them.
This is TextureLoader,i think it correctly loads texture on idx position.
public int[] texture = new int[10];
public int loadTexture(Context context, int resource,int idx){
GLES20.glGenTextures(idx, texture, 0);
BitmapFactory.Options bo = new BitmapFactory.Options();
Bitmap tex = BitmapFactory.decodeResource(context.getResources(), resource, bo);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
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);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, tex, 0);
tex.recycle();
if(texture[idx] == 0){
// Displays error
}
return texture[idx];
}
This is my render and I have no idea how to select loaded texture.
int mPositionHandle =
GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image,
"a_texCoord" );
GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image,
"uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image,
"s_texture" );
GLES20.glUniform1i ( mSamplerLoc, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
It looks like you have most of what you need, assuming that you filled the buffers with the necessary data. There's one call in your code where the arguments are not what you must have intended:
GLES20.glGenTextures(idx, texture, 0);
With the Java bindings in Android, the first argument is the number of ids you want to generate, the second an array of ids, the 3rd the start index in the array where the generated ids are stored. So to generate one id, and store it as texture[idx], the correct arguments are:
GLES20.glGenTextures(1, texture, idx);
Then, for the core part of your question, the call you are looking for is glBindTexture(). This call defines which specific texture most texture-related OpenGL operations use. You will need this call in multiple places.
In your loadTexture() method, both GLES20.glTexParameteri() and GLUtils.texImage2D() operate on the currently bound texture. So before those calls, you need to add this call to bind your new texture:
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[idx]);
You need the same call before the draw operation. So somewhere in your render method, before you call GLES20.glDrawElements(), use a glBindTexture() call that looks just like the one above, with the idx value of the texture you want to use. This is where you really choose which of the textures you loaded is applied during rendering.
There are mechanisms that allow you to bind multiple textures at the same time. This is mainly useful if your shader needs to sample from multiple textures. You most likely won't need this yet. But once you get to that point, you will want to read up on "texture units", and look up the glActiveTexture() call.