2

EDIT: figured it out, see answer below.

I'm having a problem trying to render to a texture in OpenGL ES 2.0 on Android (NDK) on Samsung Galaxy S

More specifically i am using a Framebuffer to render to a texture and then i draw from that texture onto the backbuffer - in the emulator (running 4.2.2) and on a Galaxy S2 it renders perfectly, and the same goes for running on a number of iOS devices with the same code.

The Galaxy S is running 2.3.3 (i can't convince the emulator to do this in 2.3.3).

When i set the texture size to 1024x1024 it looks as though it is still being stored in a 512x512 texture, or like some heavy compression is going on, this happens only on the Galaxy S, both an S2, the emulator and the iOS devices render flawlessly.

If i set the texture to 512x512 it seems to render pretty much ok on the Galaxy S, nothing glaring is wrong but you will notice some of the same blurring happing just to a much lesser extent

Screenshot of 1024x1024

Screensshot of 1024x1024

Screenshot og 512x512

Screenshot og 512x512

On both images the upper 4 items are drawn first to the texture and then from there unto the backbuffer (the flaw in the black one is also a Galaxy S only problem, but i'm not considdering it related)

I can load a 1024x1024 texture and render from that just fine, and if i use glReadPixels on the texture's render buffer it looks just fine too (GL ES unfortunately doesn't support reading the pixels off the underlying texture directly)

Saved framebuffer at 1024x1024

As you may note it suffers none of the blurryness not even the light kind of the 512x512 version.

To further mystify me i have an older project in Java running OpenGL ES 1.1 that renders to a 1024x1024 texture without any problems on the same Galaxy S device, i have not been desperate enough to write a complete ES 2.0 rendering in Java to see if that makes a difference and i haven't tried ES 1.1 with the NDK as the OES extension methods for the framebuffer create linker errors (it's possible there is a lib that could be linked, i may go there if no one has any better ideas)

I have however tried creating the framebuffer and texture in java and passing the handles to the native code but it makes no difference.

Any pointers, guesses, hunches, magic keywords for google, anything is very much appreciated i have spent 12 hours straight today trying to figure this out and i have made no progress what so ever, i'm nearing desperate.

Following is snippets of code that may be relevant, don't hesitate to ask for more (the entire project is thousands of lines spanning 3 platforms at this point so i have tried picking the most relevant parts.)

Code for creating the framebuffer:

glGenFramebuffers(1, &FFrameBufferID);
glBindFramebuffer(GL_FRAMEBUFFER, FFrameBufferID);
glGenRenderbuffers(1, &FDepthBufferID);
glBindRenderbuffer(GL_RENDERBUFFER, FDepthBufferID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, FDepthBufferID);

glGenTextures(1, &FTextureID);
glBindTexture(GL_TEXTURE_2D, FTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Tried both with and without:
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

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, FTextureID, 0);

GLenum OStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (OStatus != GL_FRAMEBUFFER_COMPLETE) {
    Dev::Log(SGString("framebuffer creation failed: ") + (int) OStatus);
}

Vertex shader:

void main(void) {
    gl_Position = Projection * vec4(Position, 1.0);
    TextureCoordsOut = TextureCoords;
    ParamOut = Param;
    ColorOut = Color;
}

Projection matrix:

matrix[0]  = 2.0 / (right - left);
matrix[1]  = 0.0;
matrix[2]  = 0.0;
matrix[3] = 0.0;

matrix[4]  = 0.0;
matrix[5]  = 2.0 / (top - bottom);
matrix[6]  = 0.0;
matrix[7] = 0.0;

matrix[8]  = 0.0;
matrix[9]  = 0.0;
matrix[10]  = -2.0 / (far - near);
matrix[11] = 0.0;

matrix[12]  = -(right + left) / (right - left);
matrix[13]  = -(top + bottom) / (top - bottom);
matrix[14] = -(far + near) / (far - near);
matrix[15] = 1.0;

Rendering:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);

glVertexAttribPointer(FPositionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer());
glVertexAttribPointer(FTextureCoordsSlot, 2, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer() + (sizeof(float) * 3));
glVertexAttribPointer(FParamSlot, 1, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer()+ (sizeof(float) * 5));
glVertexAttribPointer(FColorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer()+ (sizeof(float) * 6));

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, OTexture->TextureID());
glUniform1i(FTextureUniform, 0);

glDrawArrays(GL_TRIANGLES, 0, count);

1 Answers1

1

I stumbled over a tiny hint that lead me to the answer, the problem was the precision of the texture coordinates I had simply copied from a sample:

varying lowp vec2 TextureCoordsOut;

having no idea what lowp meant I just ignored it - big mistake - I changed it to

varying highp vec2 TextureCoordsOut;

and now it works perfectly, why it works on all the other devices in spite being lowp is beyond me though

its possible mediump will work too but I figured I'd just for go highp to test it.

Jouni Helske
  • 6,427
  • 29
  • 52
  • 1
    lowp covers the -2..2 interval which is pretty low considering it may use as low as 8 bits and you it has to linearly blend in 1/800 increments. Precision gets lost fast that way. Why it works everywhere else ? Simple, precision qualifiers are implementation dependent. Some may default lowp to mediump (or highp like on desktops) and use 16/32 bits instead. There's a function glGetShaderPrecisionFormat that can tell you exactly how many bits a precision qualifier uses. – RelativeGames Mar 27 '13 at 19:39
  • Hi Anders, Here i am facing some problem while using Samsung Galaxy note2, for run opengl es2.0 auto cad app in android. I cant draw multiple lines or circles, when I draw line again, it erased previous line or circle dawned already. Please see this link and understand my question and see my sample code and help me.. http://stackoverflow.com/questions/17187032/why-my-opengl-output-differs-for-various-devices – harikrishnan Jun 20 '13 at 06:08