How can i render captured frames from ndk into encoder input surface? - android

i'm trying to capture with camera and record frames as mp4 file in android Oreo.
I implemented the capture progress using NDK.
After that, i did create preview surface(GLSurfaceview) and get input surface from encoder(Mediacodec).
However, I don't know how to render captured frames to encoder's input surface.
/* This is onDrawFrame of Renderer in GLSurfaceView instance
* The native function onDrawFrame(texMatrix) is called */
#Override
public void onDrawFrame(GL10 gl) {
synchronized (lock) {
if ( frameAvailable ) {
Log.d("yoo", "Frame availablee...updating");
surfaceTexture.updateTexImage();
surfaceTexture.getTransformMatrix(texMatrix);
frameAvailable = false;
}
}
onDrawFrame(texMatrix);
}
/* This is drawing function in NDK part that is executed when onDrawFrame(texMatrix) is called */
static void drawFrame ( JNIEnv* env, jfloatArray texMatArray )
{
LOGD("DrawFrame called");
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
glClearColor ( 0, 0, 0, 1 );
glUseProgram ( prog );
// Configure main transformations
float mvp[] = {
1.0f, 0, 0, 0,
0, 1.0f, 0, 0,
0, 0, 1.0f, 0,
0, 0, 0, 1.0f
};
// give mvp data to shader
glUniformMatrix4fv ( mvpMatrix, 1, false, mvp );
// Prepare texture for drawing
glActiveTexture ( GL_TEXTURE0 );
glBindTexture ( GL_TEXTURE_EXTERNAL_OES, textureId );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
// Pass SurfaceTexture transformations to shader
float* tm = env->GetFloatArrayElements ( texMatArray, 0 );
glUniformMatrix4fv ( texMatrix, 1, false, tm );
env->ReleaseFloatArrayElements ( texMatArray, tm, 0 );
// Set the SurfaceTexture sampler
glUniform1i ( texSampler, 0 );
// specify color to mix with camera frames
float c[] = { 1, 1, 1, 1 };
glUniform4fv ( color, 1, (GLfloat*)c );
// Size of the window is used in fragment shader
// to split the window
float sz[2] = {0};
sz[0] = width/2;
sz[1] = height/2;
glUniform2fv ( size, 1, (GLfloat*)sz );
// Set up vertices/indices and draw
glBindBuffer ( GL_ARRAY_BUFFER, buf[0] );
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, buf[1] );
glEnableVertexAttribArray ( vtxPosAttrib ) ;
glVertexAttribPointer ( vtxPosAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)0 );
glEnableVertexAttribArray ( uvsAttrib );
glVertexAttribPointer ( uvsAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(3 * sizeof(float) ) );
glViewport ( 0, 0, width, height );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
}
Actualy, i tried to create the encoder instance of Mediacodec and receive the input surface of that and render the captured frames. (I refered grafika's exmaple.)
However, i don't know the way how to render captured frames after rendering captured frames into GLSurfaceView.
-EDIT-
I tried to create EGLSurface using input surface of encoder but the below error message is showed.
android.opengl.EGL14.eglCreateWindowSurface(mEGLCore.getDisplay(), mEGLCore.getConfig(), mEncoderSurface, surfaceAttribs, 0);
/* error message */
E/BufferQueueProducer: [GraphicBufferSource] connect: BufferQueue has been abandoned
E/libEGL: eglCreateWindowSurface: native_window_api_connect (win=0x92b7f808) failed (0xffffffed) (already connected to another API?)
E/libEGL: eglCreateWindowSurface:693 error 3003 (EGL_BAD_ALLOC)
Any reply will be appreciated.

Related

opengl es multi-pass blurring the second pass overrides the first pass

I am not very good with opengl es so any beginner mistake in the code is justified. I have implemented the draw function to execute the same fragment shader with different uniform variable called blurringDirection, if I execute the horizontal blurring alone(by setting the blurringDirection to 0) it works fine, also the same for the vertical but when I try to combine them together the second overrides the first. Here is my draw() function:
fun draw(
mvpMatrix: FloatArray?,
vertexBuffer: FloatBuffer?,
firstVertex: Int,
vertexCount: Int,
coordsPerVertex: Int,
vertexStride: Int,
texMatrix: FloatArray?,
texBuffer: FloatBuffer?,
textureId: Int,
texStride: Int,
) {
//creating an intermediate texture
val intermediateTexIdArr = IntArray(1)
GLES20.glGenTextures(1, intermediateTexIdArr, 0)
glBindTexture(GL_TEXTURE_2D, intermediateTexIdArr[0])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 360, 0, GL_RGBA, GL_UNSIGNED_BYTE, null)
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_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glBindTexture(GL_TEXTURE_2D, 0)
//creating a framebuffer and attaching the newly created texture to it.
val frameBufferIdArr = IntArray(1)
GLES20.glGenFramebuffers(1, frameBufferIdArr, 0)
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferIdArr[0])
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTexIdArr[0], 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Timber.d("KingArmstring: Framebuffer status is complete? ${status == GL_FRAMEBUFFER_COMPLETE}") //this prints true
if (status != GL_FRAMEBUFFER_COMPLETE) throw Exception("Framebuffer is not setup correctly")
//bind to the framebuffer instead of to the screen.
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferIdArr[0])
glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
// Select the program.
glUseProgram(programHandle)
checkGlError("glUseProgram")
// Set the texture.
glActiveTexture(GL_TEXTURE0)
glBindTexture(textureTarget, textureId) //textureId is the main id that has the original image
// Copy the model / view / projection matrix over.
glUniformMatrix4fv(mvpMatrixLoc, 1, false, mvpMatrix, 0)
checkGlError("glUniformMatrix4fv")
// Copy the texture transformation matrix over.
glUniformMatrix4fv(texMatrixLoc, 1, false, texMatrix, 0)
checkGlError("glUniformMatrix4fv")
// Enable the "aPosition" vertex attribute.
glEnableVertexAttribArray(positionLoc)
checkGlError("glEnableVertexAttribArray")
// Connect vertexBuffer to "aPosition".
glVertexAttribPointer(
positionLoc, coordsPerVertex,
GL_FLOAT, false, vertexStride, vertexBuffer
)
checkGlError("glVertexAttribPointer")
// Enable the "aTextureCoord" vertex attribute.
glEnableVertexAttribArray(textureCoordLoc)
checkGlError("glEnableVertexAttribArray")
// Connect texBuffer to "aTextureCoord".
glVertexAttribPointer(
textureCoordLoc, 2,
GL_FLOAT, false, texStride, texBuffer
)
checkGlError("glVertexAttribPointer")
if (programType == VIDEO_STREAM) {
glUniform1f(brightnessLoc, brightness)
glUniform1f(contrastLoc, contrast)
glUniform1f(saturationLoc, saturation)
glUniform1f(gammaLoc, gamma)
glUniform1f(whiteBalanceTempLoc, whiteBalanceTemp)
glUniform1f(whiteBalanceTintLoc, whiteBalanceTint)
glUniform1f(whiteBalanceEnabledLoc, whiteBalanceEnabled)
glUniform1f(hueAdjLoc, hueAdj)
glUniform1f(hueAdjEnabledLoc, hueAdjEnabled)
glUniform1f(sharpnessLoc, sharpness)
glUniform1f(imageWidthFactorLoc, imageWidthFactor)
glUniform1f(imageHeightFactorLoc, imageHeightFactor)
}
glUniform1i(blurringDirectionLoc, 0)
// Draw the rect.
glDrawArrays(GL_TRIANGLE_STRIP, firstVertex, vertexCount)//rendering to the framebuffer with the blurringDirection = 0
checkGlError("glDrawElements")
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, intermediateTexIdArr[0])
glUniform1i(blurringDirectionLoc, 1)
glDrawArrays(GL_TRIANGLE_STRIP, firstVertex, vertexCount)//drawing on the screen second pass with the blurringDirection = 1.
glDisableVertexAttribArray(positionLoc)
glDisableVertexAttribArray(textureCoordLoc)
GLES20.glDeleteFramebuffers(1, frameBufferIdArr, 0)
GLES20.glDeleteTextures(1, intermediateTexIdArr, 0)
}

glTexSubImage2D is slower with Pixel Buffer Objects

I am using PBO in opengl es3 on android but after using them, performance of data unpacking has degraded. Please help me in finding fault in the code.
Background: My app consist of a module which generates images at a very fast rate. These images are uploaded to textures which are finally drawn on TextureView. Bottleneck in my app is time taken in uploading images to textures.
I decided to try PBOs to improve this perf. Below is my code:
One time initialization
CheckGLErr( glGenTextures( 1, &texName ) );
if( usePBO )
{
CheckGLErr( glGenBuffers( 1, &pboId ) );
CheckGLErr( glBindBuffer( GL_PIXEL_UNPACK_BUFFER, pboId ) );
CheckGLErr( glBufferData( GL_PIXEL_UNPACK_BUFFER, textureSize, 0, GL_STREAM_DRAW ) );
CheckGLErr( glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0 ) );
}
glBindTexture( GL_TEXTURE_2D, texName );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, windowWidth, windowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
glBindTexture( GL_TEXTURE_2D, 0 );
RenderLoop:
CheckGLErr(glClearColor(0, 1.0f, 0, 1));
CheckGLErr(glClear(GL_COLOR_BUFFER_BIT));
glBindTexture( GL_TEXTURE_2D, texName );
if( usePBO )
{
CheckGLErr(glBindBuffer( GL_PIXEL_UNPACK_BUFFER, pboId ));
void* pBuff = ::glMapBufferRange( GL_PIXEL_UNPACK_BUFFER, 0, textureSize , GL_MAP_WRITE_BIT );
memcpy( pBuff, buffer.get(), textureSize );
CheckGLErr(glUnmapBuffer( GL_PIXEL_UNPACK_BUFFER ));
}
//std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, windowWidth, windowHeight, GL_RGBA, GL_UNSIGNED_BYTE, usePBO ? 0 : buffer.get() );
// Setup texture properties.
CheckGLErr(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
CheckGLErr(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
CheckGLErr(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
CheckGLErr(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
CheckGLErr( glUseProgram( programObject ) );
// Enable position vertex attribute. Its size is 3 floats corresponding for co-ordinates in three directions.
CheckGLErr(glEnableVertexAttribArray(0));
CheckGLErr(glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * sizeof(float)/*vertexStride*/, (const GLvoid *)0));
// Enable UV vertex attribute which starts after position. Hence offset = 3 floats.
CheckGLErr(glEnableVertexAttribArray(1));
CheckGLErr(glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * sizeof(float)/*vertexStride*/, (const GLvoid *)(3*sizeof(float))/*offset worth position*/));
// Setup ViewPort
CheckGLErr(glViewport(0, 0, windowWidth, windowHeight));
if(usePBO )
CheckGLErr( glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0 ) );
CheckGLErr(glDrawElements(GL_TRIANGLE_STRIP, _countof(indices), GL_UNSIGNED_SHORT, (const GLvoid *)0x00000000));
eglSwapBuffers(eglDisplay, eglWindowSurface);
Measurements Done:
On Nexus 7 (4.4.4) Adreno GPU
Screen Size = 1624 * 1200 pixels
Without PBO : 17 ms
With PBO : 18 ms (~ 5ms for buffer population and rest in glTexSubImage2D call)
On Nexus 6 (5.0)
Screen Size = 2042 * 1440 pixels
Without PBO : 6 ms
With PBO : 20 ms
My assumption was on using PBOs glTexSubImage2D should return instanteously(or at least in < 5ms) because image data is already in VRAM but in fact it is taking much longer specially on Nexus 6.
As an experiment I put std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); between glUnmapBuffer and glTexSubImage2d to see whether it makes any difference in time taken by only glTexSubImage2D but it remained same.

Draw to framebuffer object, then blit to primary display (GLES 3.0)

I am attempting to create a framebuffer object, and then blit it to the primary display. The purpose of this to to cache a screen shot that I can blit to the display whenever I want without re-rendering the object. I am using Open GLES 3.0 with android NDK.
I created a frame buffer in the normal way.
GLuint framebuffer = NULL;
glGenFramebuffers( 1, &framebuffer );
glBindFramebuffer( GL_FRAMEBUFFER, framebuffer );
GLuint colorRenderBuffer = NULL;
glGenRenderbuffers( 1, &colorRenderbuffer );
glBindRenderbuffer( GL_RENDERBUFFER, colorRenderbuffer );
glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA8, engine->width, engine->height );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer );
GLuint depthRenderbuffer = NULL;
glGenRenderbuffers( 1, &depthRenderbuffer );
glBindRenderbuffer( GL_RENDERBUFFER, depthRenderbuffer );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, engine->width, engine->height );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer );
GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if (status != GL_FRAMEBUFFER_COMPLETE) {
LOGI( "failed to make complete framebuffer object %d", status );
}
else {
LOGI( "Frame buffer is complete." );
}
This works without error. I then am able to edit the frame buffer, successfully.
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, framebuffer );
glBindFramebuffer( GL_READ_FRAMEBUFFER, framebuffer );
// Just fill the screen with a color.
glClearColor( red, green, blue, 255 );
glClear( GL_COLOR_BUFFER_BIT );
read_pixels( ); //wrapper for glReadPixels. Shows that all pixels in the frame buffer object have the desired color.
However, attempting to blit this to the main draw buffer fails.
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glBindFramebuffer( GL_READ_FRAMEBUFFER, framebuffer );
glReadBuffer( GL_COLOR_ATTACHMENT0 );
glBlitFramebuffer( 0, 0, engine->width, engine->height, 0, 0, engine->width, engine->height, GL_COLOR_BUFFER_BIT, GL_LINEAR );
LOGI("GL error after blit: %d", glGetError()); //no error reported
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 );
read_pixels( engine ); //gives zero'd buffer (wrong result)
eglSwapBuffers( engine->display, engine->surface ); //shows a black screen, unless I use glClearColor directly on the primary display buffer.
I was able to get around the problem by using a texture (instead of a render buffer) frame buffer object, drawing to that frame buffer, and then drawing that frame buffer texture to the default buffer. This isn't really an answer, but a work around, so I'd still appreciate it if anyone has an answer to the original question.
For reference, I include the key code below:
GLuint LoadFrameBufferTexture( ESContext *context, int width, int height ) {
glGenFramebuffers( 1, &(context->framebuffer) );
glBindFramebuffer( GL_FRAMEBUFFER, context->framebuffer );
// create the texture
GLuint texture;
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0 );
GLuint depthRenderbuffer;
glGenRenderbuffers( 1, &depthRenderbuffer );
glBindRenderbuffer( GL_RENDERBUFFER, depthRenderbuffer );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer );
GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if (status != GL_FRAMEBUFFER_COMPLETE) {
LOGI("failed to make complete framebuffer object ");
} else {
LOGI("Frame buffer is complete.");
}
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
return texture;
}
void draw_frame(int red, int green, int blue) {
glBindFramebuffer( GL_FRAMEBUFFER, esContext->framebuffer );
glClearColor( red, green, blue, 255 );
glClear( GL_COLOR_BUFFER_BIT );
glBindFramebuffer(GL_FRAMEBUFFER, 0 );
DrawFrame( esContext );
eglSwapBuffers( engine->display, engine->surface );
}
void DrawFrame( ESContext *esContext ) {
UserData *userData = (UserData *)esContext->userData;
GLfloat vVertices[] = {-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
glViewport( 0, 0, esContext->width, esContext->height );
glUseProgram( userData->programObject );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof( GLfloat ), vVertices );
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof( GLfloat ), &vVertices[3] );
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, userData->frameTexId );
glUniform1i( userData->baseMapLoc, 0 );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
}

Render to Framebuffer in OpenGL ES on Android with QT

I try to render in a FBO Object with QT 5.2, on PC everything works fine, but the Mobile-Screen stays black. BTW. It's a Android phone.
Here's the code for the initalisation :
GLANN::GLANN(unsigned int width, unsigned int height, unsigned int renderPasses, Scene *renderScene,
QWidget *parent, QGLWidget *shareWidget)
: QGLWidget(parent, shareWidget)
{
makeCurrent();
setFixedWidth(width);
setFixedHeight(height);
this->width = width;
this->height = height;
qsrand((uint)QTime::currentTime().msec());
mScene = renderScene;
SceneImage = renderScene->getSceneImage();
numObjects = SceneImage->width();
renderedImage = new Playground(texSize,texSize);
}
void GLANN::initializeGL(){
setAutoBufferSwap(true);
initializeGLFunctions();
glEnable(GL_CULL_FACE);
glClearColor(0.0, 0.0, 0.0, 0.0);
initShader();
initTextures();
// Generate 2 VBOs
glGenBuffers(1, &vboId0);
glGenBuffers(1, &vboId1);
VertexData vertices[] = {
// Vertex data for face 0
{QVector3D(-1.0, -1.0, 1.0), QVector2D(0.0, 0.0)}, // v0
{QVector3D( 1.0, -1.0, 1.0), QVector2D(1.0, 0.0)}, // v1
{QVector3D(-1.0, 1.0, 1.0), QVector2D(0.0, 1.0)}, // v2
{QVector3D( 1.0, 1.0, 1.0), QVector2D(1.0, 1.0)}, // v3
};
// Transfer vertex data to VBO 0
glBindBuffer(GL_ARRAY_BUFFER, vboId0);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), vertices, GL_STATIC_DRAW);
GLushort indices[] = {
0, 1, 2, 3, 3,
};
// Transfer index data to VBO 1
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId1);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 5 * sizeof(GLushort), indices, GL_STATIC_DRAW);
//Init the Framebuffer
initFbo();
// Use QBasicTimer because its faster than QTimer
timer.start(0, this);
}
bool GLANN::initFbo(){
fbo = new QOpenGLFramebufferObject(texSize, texSize);
return true;
}
And here for the Rendering:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Set random seed
program.setUniformValue("seedX", ((float)qrand()/RAND_MAX));
program.setUniformValue("seedY", ((float)qrand()/RAND_MAX));
//Set number of alredy rendered passes
program.setUniformValue("numRenderPass",mRenderPasses);
//Set program to fbo render mode
program.setUniformValue("fbo",true);
//Bind last rendered Image
//pixelsRenderedImage = bindTexture(*renderedImage);
//Load Identity
//glLoadIdentity();
//Move to rendering point
//glTranslatef( -1.0, -1.0, 0.0f );
// Draw geometry
// Tell OpenGL which VBOs to use
// Render to our framebuffer
fbo->bind();
glViewport(0,0,texSize,texSize);
// Tell OpenGL which VBOs to use
glBindBuffer(GL_ARRAY_BUFFER, vboId0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId1);
// Offset for position
int offset = 0;
// Tell OpenGL programmable pipeline how to locate vertex position data
int vertexLocation = program.attributeLocation("a_position");
program.enableAttributeArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
// Offset for texture coordinate
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate vertex texture coordinate data
int texcoordLocation = program.attributeLocation("a_texcoord");
program.enableAttributeArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pixelsRenderedImage);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pixelsScene);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, pixelsRandom);
// Draw cube geometry using indices from VBO 1
glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, 0);
fbo->release();
pixelsRenderedImage = fbo->takeTexture();
//Set Program to screen frendering
program.setUniformValue("fbo",false);
//Set Viewport back to default
glViewport(0,0,width,height);
//Render To Screen
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pixelsRenderedImage);
// Draw quad geometry using indices from VBO 1
glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, 0);
Hope it's clear what I'm trying to do here...
EDIT : REMOVED glEnable(TEXTURE_2D).
Still getting a blackscreen but no Errors from glError();
GLANN::GLANN(unsigned int width, unsigned int height, unsigned int renderPasses, Scene *renderScene,
QWidget *parent, QGLWidget *shareWidget)
: QGLWidget(parent, shareWidget)
{
setFixedWidth(width);
setFixedHeight(height);
this->width = width;
this->height = height;
qsrand((uint)QTime::currentTime().msec());
mScene = renderScene;
SceneImage = renderScene->getSceneImage();
numObjects = SceneImage->width();
renderedImage = new Playground(texSize,texSize);
}
void GLANN::initializeGL(){
//setAutoBufferSwap(true);
makeCurrent();
initializeGLFunctions();
qDebug() << glGetError() << "Line 28";
//glEnable(GL_CULL_FACE);
glClearColor(0.0, 0.0, 0.0, 0.0);
initShader();
qDebug() << glGetError() << "Line 36";
initTextures();
qDebug() << glGetError() << "Line 40";
// Generate 2 VBOs
glGenBuffers(1, &vboId0);
glGenBuffers(1, &vboId1);
VertexData vertices[] = {
// Vertex data for face 0
{QVector3D(-1.0, -1.0, 1.0), QVector2D(0.0, 0.0)}, // v0
{QVector3D( 1.0, -1.0, 1.0), QVector2D(1.0, 0.0)}, // v1
{QVector3D(-1.0, 1.0, 1.0), QVector2D(0.0, 1.0)}, // v2
{QVector3D( 1.0, 1.0, 1.0), QVector2D(1.0, 1.0)}, // v3
};
// Transfer vertex data to VBO 0
glBindBuffer(GL_ARRAY_BUFFER, vboId0);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), vertices, GL_STATIC_DRAW);
GLushort indices[] = {
0, 1, 2, 3, 3,
};
// Transfer index data to VBO 1
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId1);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 5 * sizeof(GLushort), indices, GL_STATIC_DRAW);
qDebug() << glGetError() << "Line 57";
//Init the Framebuffer
initFbo();
qDebug() << glGetError() << "Line 62";
// Use QBasicTimer because its faster than QTimer
timer.start(0, this);
}
bool GLANN::initFbo(){
fbo = new QOpenGLFramebufferObject(texSize, texSize);
return true;
}
void GLANN::resizeGL(int w, int h){
glViewport(0,0,w,h);
}
void GLANN::mouseMoveEvent(QMouseEvent* event){
if(event->buttons() == Qt::LeftButton){
LineObject newPoly(xTemp,yTemp, 1.0f*event->pos().x()/width, 1.0f-1.0f*event->pos().y()/width,qRgba(255,255,255,255),0.4,0.5,0.3,0.0);
mScene->addObject(newPoly);
SceneImage = mScene->getSceneImage();
numObjects = SceneImage->width();
//Bind WeightmapTexture
pixelsScene = QGLWidget::bindTexture(*SceneImage);
qDebug() << xTemp << yTemp << numObjects;
//Bind last rendered Image
renderedImage->fill(qRgba(0,0,0,255));
pixelsRenderedImage = bindTexture(*renderedImage);
mRenderPasses = 0;
// Set number of Objects
program.setUniformValue("numObjects",numObjects);
xTemp = 1.0f*event->pos().x()/width;
yTemp = 1.0f-1.0f*event->pos().y()/height;
}
}
void GLANN::mousePressEvent(QMouseEvent* event){
if(event->button() == Qt::LeftButton){
xTemp = 1.0f*event->pos().x()/width;
yTemp = 1.0f-1.0f*event->pos().y()/height;
}
}
void GLANN::paintGL(){
render();
//getFeedbackTexture();
//increment number of rendered passes
mRenderPasses++;
}
void GLANN::render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Set random seed
program.setUniformValue("seedX", ((float)qrand()/RAND_MAX));
program.setUniformValue("seedY", ((float)qrand()/RAND_MAX));
//Set number of alredy rendered passes
program.setUniformValue("numRenderPass",mRenderPasses);
//Set program to fbo render mode
program.setUniformValue("fbo",true);
//Bind last rendered Image
//pixelsRenderedImage = bindTexture(*renderedImage);
//Load Identity
//glLoadIdentity();
//Move to rendering point
//glTranslatef( -1.0, -1.0, 0.0f );
// Draw geometry
// Tell OpenGL which VBOs to use
// Render to our framebuffer
fbo->bind();
glViewport(0,0,texSize,texSize);
// Tell OpenGL which VBOs to use
glBindBuffer(GL_ARRAY_BUFFER, vboId0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId1);
// Offset for position
int offset = 0;
// Tell OpenGL programmable pipeline how to locate vertex position data
int vertexLocation = program.attributeLocation("a_position");
program.enableAttributeArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
// Offset for texture coordinate
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate vertex texture coordinate data
int texcoordLocation = program.attributeLocation("a_texcoord");
program.enableAttributeArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
qDebug() << glGetError() << "Line 167";
//glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pixelsRenderedImage);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pixelsScene);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, pixelsRandom);
// Draw cube geometry using indices from VBO 1
glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, 0);
qDebug() << glGetError() << "Line 183";
fbo->release();
pixelsRenderedImage = fbo->texture();
//Set Program to screen frendering
program.setUniformValue("fbo",false);
//Set Viewport back to default
glViewport(0,0,width,height);
//Render To Screen
//glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pixelsRenderedImage);
// Draw quad geometry using indices from VBO 1
glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, 0);
qDebug() << glGetError();
}
Problem is probably caused by this:
Qt Android. Get device screen resolution
And this:
Errors after changed OpenGL code from ES 1.0 to ES 2.0

Texture won't appear using native code to load it with opengl es on android

I'm trying to apply a texture to an object in opengl es from the native side and I have no idea why it isn't showing up. I have a couple random objects drawn on the screen, and they're all visible and everything. I applied color to some shapes using glColor4f and that works fine. I'm trying to use a texture on the last object that gets drawn but it ends up being the same color as the one previous.
I was originally loading the texture from a png, but I decided to simplify things by loading it from a file that contains raw RGB data. It's 16 pixels x 16 pixels, and I've tried sizes up to 512 by 512 with the same result.
Here's how I'm initializing everything:
bool Activity::_initGL () {
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLint dummy, format;
EGLint numConfigs;
EGLConfig config;
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(app->window, 0, 0, format);
surface = eglCreateWindowSurface(display, config, app->window, NULL);
context = eglCreateContext(display, config, NULL, NULL);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGE("Unable to eglMakeCurrent");
return false;
}
eglQuerySurface(display, surface, EGL_WIDTH, &width);
eglQuerySurface(display, surface, EGL_HEIGHT, &height);
glViewport(0,0, width, height);
}
And then I enable the necessary things and try to create the texture:
void postInit () {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glDisable( GL_BLEND );
glDisable( GL_LIGHTING );
// glEnable(GL_CULL_FACE);
glEnable( GL_TEXTURE_2D );
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
glClearColor(0,0,0,1);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glMatrixMode( GL_MODELVIEW );
GLuint texIDarray[1];
glGenTextures( 1, texIDarray );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, texIDarray[0] );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)16, (GLsizei)16, 0, GL_RGB, GL_UNSIGNED_BYTE, protData);
}
And here's where the texture gets drawn, someday:
void drawImpl () {
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
// glDisable(GL_TEXTURE_2D);
// glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// glEnableClientState(GL_VERTEX_ARRAY);
// glViewport(0, 0, wid, hei);
#define fX(x) ((int)(x * (1 << 16)))
static int verts[6] = {
0,0,
65536,0,
0,30000
};
glVertexPointer(2, GL_FIXED, 0, verts);
// glColor4f(1,0,1,1);
glDrawArrays(GL_TRIANGLES, 0, 3);
static int poo[12] = {
40000,-5000,
40000,-30000,
60000,-5000,
60000,-5000,
40000,-30000,
60000,-30000
};
glVertexPointer(2, GL_FIXED, 0, poo);
// glColor4f(1,1,1,1);
glDrawArrays(GL_TRIANGLES, 0, 6);
static int pee[12] = {
40000, 5000,
60000, 5000,
60000,30000,
40000, 5000,
60000,30000,
40000,30000
};
glVertexPointer(2, GL_FIXED, 0, pee);
// glColor4f(1,0,1,1);
glDrawArrays(GL_TRIANGLES, 0, 6);
glEnable(GL_TEXTURE_2D);
static int squareVerts[12] = {
0,0,
fX(1),0,
0,fX(1),
0,fX(1),
fX(1),0,
fX(1),fX(1)
};
static int texCoords[12] = {
0,0,
fX(1),0,
0,fX(1),
0,fX(1),
fX(1),0,
fX(1),fX(1)
};
//glTranslatef( (float)-.25, (float)-.5, (float)0);
// glColor4f(0,0,0,0);
// glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTexture( GL_TEXTURE0 );
// glBindTexture(GL_TEXTURE_2D, texID);
glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameterx( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterx( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glVertexPointer(2, GL_FIXED, 0, squareVerts);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
// glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable( GL_TEXTURE_2D );
glDrawArrays(GL_TRIANGLES, 0, 6);
// glDisableClientState(GL_VERTEX_ARRAY);
// glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
I deliberately left some of the commented out things to show the other things I have tried doing.
I am totally at a dead end with this right now. If anyone has any suggestions or anything it would make me super happy, and that is good.
Seems like you messed up your texture coordinates.. They should be between 0 and 1, not between 0 and 1<<16. Another thing is your "glColor4f" will also affect your texture by modulating it and for normal texture draw it needs to be set to (1,1,1,1).

Categories

Resources