in my android App, i have a Frame Buffer Object that takes me the rendered Scene As a texture.
the app is an Origami game and user can fold a paper freely:
in every Fold, the current rendered scene saves to a texture using fbo and then i redraw the paper with new coordinates with new texture attached to it, to seem like folded paper. and this way the user can fold the paper as many time as he wants.
I want in every frame Check the rendered scene, to determinate does the user riches to the final shape (assume that i have the final shape in a 2d-array with 0 and 1 filled, 0 for transparency and 1 for colored pixels)
what i want, is to some How, Convert this Texture to A 2d-Array filled with 0 and 1,
0 for transparency pixel, and 1 for Colored pixel of texture.
i need this to then compare this result with a previously Known 2d-Array to determinate if the texture is the shape i want or not.
is it possible to save the texture data to an array?
i cant use glreadPixels because it is so heavy and its not possible to call it every frame.
here is the FBO class (i want to have renderTex[0] as array):
public class FBO {
int [] fb, renderTex;
int texW;
int texH;
public FBO(int width,int height){
texW = width;
texH = height;
fb = new int[1];
renderTex= new int[1];
}
public void setup(GL10 gl){
// generate
((GL11ExtensionPack)gl).glGenFramebuffersOES(1, fb, 0);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glGenTextures(1, renderTex, 0);// generate texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, renderTex[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
//texBuffer = ByteBuffer.allocateDirect(buf.length*4).order(ByteOrder.nativeOrder()).asIntBuffer();
//gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,GL10.GL_MODULATE);
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, texW, texH, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, null);
gl.glDisable(GL10.GL_TEXTURE_2D);
}
public boolean RenderStart(GL10 gl){
Log.d("TextureAndFBO", ""+renderTex[0] + " And " +fb[0]);
// Bind the framebuffer
((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, fb[0]);
// specify texture as color attachment
((GL11ExtensionPack)gl).glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, renderTex[0], 0);
int error = gl.glGetError();
if (error != GL10.GL_NO_ERROR) {
Log.d("err", "FIRST Background Load GLError: " + error+" ");
}
int status = ((GL11ExtensionPack)gl).glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES)
{
Log.d("err", "SECOND Background Load GLError: " + status+" ");;
return true;
}
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
return true;
}
public void RenderEnd(GL10 gl){
((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
gl.glColor4f(1.0f,1.0f,1.0f,1.0f);
gl.glDisable(GL10.GL_TEXTURE_2D);
}
public int getTexture(){
return renderTex[0];
}
public int getFBO(){
return fb[0];
}
}
If you are using openGL ES 3.0 and later then pbo would be a good solution. But I think you can use EGLImage. Because this only needs OpenGL ES 1.1 or 2.0.
The function to create an EGLImageKHR is:
EGLImageKHR eglCreateImageKHR(EGLDisplay dpy,
EGLContext ctx,
EGLenum target,
EGLClientBuffer buffer,
const EGLint *attrib_list)
To allocate an ANativeWindowBuffer, Android has a simple wrapper called GraphicBuffer:
GraphicBuffer *window = new GraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE);
struct ANativeWindowBuffer *buffer = window->getNativeBuffer();
EGLImageKHR *image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, *attribs);
to read pixels from an FBO use one of these two methods below:
void EGLImageTargetTexture2DOES(enum target, eglImageOES image)
void EGLImageTargetRenderbufferStorageOES(enum target, eglImageOES image)
These two methods will esablish all the properties of the target GL_TEXTURE_2D or GL_RENDERBUFFER
uint8_t *ptr;
glBindTexture(GL_TEXTURE_2D, texture_id);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
window->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &ptr);
memcpy(pixels, ptr, width * height * 4);
window->unlock();
To accomplish what you want, you need to use a PBO (Pixel Buffer Object): You can map it to an array to read it if it were a regular array.
OpenGL ARB_pixel_buffer_object extension is very close to
ARB_vertex_buffer_object. It simply expands ARB_vertex_buffer_object
extension in order to store not only vertex data but also pixel data
into the buffer objects. This buffer object storing pixel data is
called Pixel Buffer Object (PBO). ARB_pixel_buffer_object extension
borrows all VBO framework and APIs, plus, adds 2 additional "target"
tokens. These tokens assist the PBO memory manger (OpenGL driver) to
determine the best location of the buffer object; system memory,
shared memory or video memory. Also, the target tokens clearly specify
that the bound PBO will be used in one of 2 different operations;
GL_PIXEL_PACK_BUFFER_ARB to transfer pixel data to a PBO, or
GL_PIXEL_UNPACK_BUFFER_ARB to transfer pixel data from PBO.
It can be created similiar to other buffer objects:
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, size, 0, GL_DYNAMIC_READ);
Then you can read from an FBO (or a texture) easily:
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
GLubyte *array = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, size, GL_MAP_READ_BIT);
// TODO: Do your checking of the shape inside of this 'array' pointer or copy it somewhere using memcpy()
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
Here GL_COLOR_ATTACHMENT0 is used as input - see the specification of glReadBuffer for further details how to specify front or backbuffer to be used.
Related
I'm currently developing an .obj file loader on Android. I have done the basics, and the 3d mesh is drawn correctly with OpenGl. Unfortunately I have a problem in binding the texture. Let me explain with more details:
The .obj file has the following structure:
v -0.751804 0.447968 -1.430558
v -0.751802 2.392585 -1.428428
... etc list with all the vertices ...
vt 0.033607 0.718905
vt 0.033607 0.718615
... etc list with all the texture coordinates ...
f 237/1 236/2 253/3 252/4
f 236/2 235/5 254/6 253/3
... etc list with all the faces ...
The f lines idicate the index where the appropriate vertex and texture coordinates are stored, like
f vertex_index/texture_coord_index
So my program
parses the vertices and stores them in a Vector<Float>,
parses the texture coordinates and stores them in a Vector<Float>
and finally parses the faces and stores every vertex index in a Vector<Short> and every texture coordinate index in a Vector<Short>
After all this code, I'm creating the appropriate buffers:
public void buildVertexBuffer(){
ByteBuffer vBuf = ByteBuffer.allocateDirect(vertices.size() * 4);
vBuf.order(ByteOrder.nativeOrder());
vertexBuffer = vBuf.asFloatBuffer();
vertexBuffer.put(toFloatArray(vertices));
vertexBuffer.position(0);
}
where vertices is the vector that stores the float vertices
public void buildFaceBuffer(){
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(faces.size() * 2);
byteBuffer.order(ByteOrder.nativeOrder());
faceBuffer = byteBuffer.asShortBuffer();
faceBuffer.put(toShortArray(faces));
faceBuffer.position(0);
}
where faces is the vector that stores the indices and
public void buildTextureBuffer(Vector<Float> textures){
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(texturePointers.size() * 4 * 2);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
for(int i=0; i<texturePointers.size(); i++){
float u = textures.get(texturePointers.get(i) * 2);
float v = textures.get(texturePointers.get(i) * 2 + 1);
textureBuffer.put(u);
textureBuffer.put(v);
}
textureBuffer.position(0);
}
where textures are the float texture coordinates and texturePointers point to the textures' values.
The binding happens here:
public int[] loadTexture(GL10 gl, Context context){
if(textureFile == null)
return null;
int resId = getResourceId(textureFile, R.drawable.class);
if(resId == -1){
Log.d("Bako", "Texture not found...");
return null;
}
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
/*gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);*/
/*int size = bitmap.getRowBytes() * bitmap.getHeight();
ByteBuffer buffer = ByteBuffer.allocateDirect(size);
bitmap.copyPixelsToBuffer(buffer);
gl.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap.getWidth(), bitmap.getHeight(), 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_INT, buffer);*/
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
return textures;
}
Finally my draw() method of my mesh looks like this
public void draw(GL10 gl){
if(bindedTextures != null){
gl.glBindTexture(GL10.GL_TEXTURE_2D, bindedTextures[0]);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glFrontFace(GL10.GL_CW);
}
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
for(int i=0; i<parts.size(); i++){
ModelPart modelPart = parts.get(i);
Material material = modelPart.getMaterial();
if(material != null){
FloatBuffer a = material.getAmbientColorBuffer();
FloatBuffer d = material.getDiffuseColorBuffer();
FloatBuffer s = material.getSpecularColorBuffer();
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, a);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, s);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, d);
}
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, modelPart.getTextureBuffer()); // returns the texture buffer created with the buildTextureBuffer() method
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, modelPart.getNormalBuffer());
gl.glDrawElements(GL10.GL_TRIANGLES, modelPart.getFacesSize(), GL10.GL_UNSIGNED_SHORT, modelPart.getFaceBuffer());
//gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
//gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
}
When i run this application the 3d model is drawn like a charm, but the texture is somehow streched. The image that contains the texture has a red background with the appropriate image in the center and this red background is drawn onto the whole 3d model.
Well my first question is if the textureBuffer built correctly. Do i have to change the code in buildTextureBuffer() ?
And the second one; is the the draw() method correct? Does my problem have to be with the faces buffer?
So, in OpenGL a vertex is whatever combination of information describes a particular point on the model. You're using the old fixed pipeline so a vertex is one or more of a location, some texture coordinates, a normal and a colour.
In OBJ a vt is only a location. The thing that maps to the OpenGL concept of a vertex is each unique combination of — in your case — location + texture coordinate pairs given after an f.
You need a mapping whereby if the f says 56/92 then you can lookup the 56/92 and find out that you consider that to be, say, vertex 23 and have communicated suitable arrays to OpenGL such that the location value in slot 23 was the 56th thing the OBJ gave as a v and the 92nd thing it gave as a vt.
Putting it another way, OBJ files have an extra level of indirection that OpenGL does not.
It looks to me like you're not resolving that difference. A common approach would be to use a HashMap from v/vt pair to output index, building your output arrays on demand as you parse the f.
I am currently implementing a 3D viewer which basically renders a subset of all the images the user has on his SD Card. The closest matching product I would think of would be CoolIris:
It simply show a scrolling board of N tiles on screen, each showing different images, with new tiles entering the screen and showing new images.
Now for my problem: I have the program working and rendering nicely the quads. When a quad goes out of the screen, it gets recycled/released. And new quads keep on being added to the tile board before they enter the screen.
Because there can be hundreds of images, the textures need to be created and deleted on the fly (so that we don't run out of memory). The problem I have is that after I delete textures, newly created textures seem to get some IDs of other textures currently in use.
My rendering loop looks like this:
void render(GL10 gl) {
0. Move the camera
// Tile board maintenance
1. Remove tiles out of screen
2. Add new tiles which are about to enter screen
// Texture handling
3. glDeleteTextures on all unused textures followed by glFlush
4. For newly used images
- Create corresponding Bitmap
- Create the OpenGL texture, followed by glFlush
- Release the Bitmap
// Rendering
5. Render the tile (using a textured quad)
}
To give a better idea of how the data is organised, here is an overview of the classes:
TileBoard {
Image[] allImages;
Tile[] board;
}
Tile {
Image image;
}
Image {
String path;
int textureId;
int referenceCount;
}
Texture creation code:
protected void loadSingleTexture(GL10 gl, long objectId, Bitmap bmp) {
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
gl.glFlush();
if (bmp != null) bmp.recycle();
if (listener != null) listener.onTextureLoaded(gl, objectId, textures[0]);
}
Texture deletion code:
// pendingTextureUnloads is a Set<Integer>
if (pendingTextureUnloads.size() > 0) {
int[] textureIds = new int[pendingTextureUnloads.size()];
int i = 0;
Iterator<Integer> it = pendingTextureUnloads.iterator();
while (it.hasNext()) {
textureIds[i] = it.next();
}
gl.glDeleteTextures(textureIds.length, textureIds, 0);
gl.glFlush();
}
I have solved the problem: the issue was that you have to keep the texture array passed to glGenTextures and reuse it.
Here is the modified overview for the ones who will have the same problem:
Image {
String path;
int[] textureIds;
int referenceCount;
}
Texture creation code:
// Notice that I don't allocate the int[] at the beginning but use the one of the image
protected void loadSingleTexture(GL10 gl, Image img, Bitmap bmp) {
gl.glGenTextures(1, img.textureIds, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, img.textureIds[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
gl.glFlush();
if (bmp != null) bmp.recycle();
}
Texture deletion code:
foreach Image img {
gl.glDeleteTextures(img.textureIds.length, img.textureIds, 0);
}
gl.glFlush();
I know you said that you solved your issue, but I think I noticed your error in the first bit of code. Look at the while loop in your texture deletion code, you are not increasing the index i for your array, so you will continuously assign the first index until you reach the last entry in pendingTextureUnloads, the rest of the indices will be 0 (null). That might be problematic.
And by the way, I have got texture generation working by not reusing the array, just returning the index that was generated by glGenTextures. My code is to the line equal to yours, except from creating a new int array in the beginning of the method and returning the int at the first index at the end. Your code for texture generation should work, the error was just in the texture deletion.
I am trying to implement a motion blur effect in my android game.
After a lot of research I found that the best way to do that is to save the previous frame as a texture using the Frame Buffer Object and render it on top of the current frame. So seeing some nice tutorials on how to do something like that I ended up with this code which basically **render my scene on the texture and then draws the texture to the default framebuffer.
It only draw's a white texture** with a 1286 (Invalid framebuffer operation) error in gl.glGetError()
SOLVED:The problem seems to be the non power of two texture dimmensions as Jean said
int[] fb, depthRb, renderTex;
int texW = 480 * 2;
int texH = 800 * 2;
IntBuffer texBuffer;
int[] buf = new int[texW * texH];
GL11ExtensionPack gl11ep ;
void setup(GL10 gl)
{
gl11ep=(GL11ExtensionPack)gl;
fb = new int[1];
depthRb = new int[1];
renderTex = new int[1];
gl11ep.glGenFramebuffersOES(1, fb, 0);
gl11ep.glGenRenderbuffersOES(1, depthRb, 0); // the depth buffer
gl.glGenTextures(1, renderTex, 0);// generate texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, renderTex[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
texBuffer = ByteBuffer.allocateDirect(buf.length*4).order(ByteOrder.nativeOrder()).asIntBuffer();
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGB, texW, texH, 0, GL10.GL_RGB, GL10.GL_UNSIGNED_SHORT_5_6_5, texBuffer);
gl11ep.glBindRenderbufferOES(GL11ExtensionPack.GL_RENDERBUFFER_OES, depthRb[0]);
gl11ep.glRenderbufferStorageOES(GL11ExtensionPack.GL_RENDERBUFFER_OES, GL11ExtensionPack.GL_DEPTH_COMPONENT16, texW, texH);
}
boolean RenderStart(GL10 gl)
{
// Bind the framebuffer
gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, fb[0]);
// specify texture as color attachment
gl11ep.glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, renderTex[0], 0);
// attach render buffer as depth buffer
gl11ep.glFramebufferRenderbufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_DEPTH_ATTACHMENT_OES, GL11ExtensionPack.GL_RENDERBUFFER_OES, depthRb[0]);
int error = gl.glGetError();
if (error != GL10.GL_NO_ERROR) {
Tools.con("Background Load GLError: " + error) ;//here the 1286 error
}
int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES)//here always geting true
{
return false;
}
return true;
}
void RenderEnd(GL10 gl)
{
gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
gl.glClearColor(0f, 0f, 0f, 1.0f);
gl.glClear( gl.GL_DEPTH_BUFFER_BIT | gl.GL_COLOR_BUFFER_BIT);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D, renderTex[0]);
gl.glColor4f(1,1,1,1);
((GL11Ext) gl).glDrawTexfOES(0, 0, 0,800, 480);
gl.glDisable(GL10.GL_TEXTURE_2D);
}
public void onDrawFrame(GL10 gl)
{
this.RenderStart(gl);
render(gl);//render scene
this.RenderEnd(gl);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
...
setup(gl);
}
Probably you should make your texture have a power of 2 as height and width (i.e. 512x512, or even less since it's only for a blur effect). Almost every device with hardware acceleration needs that. Quick way to test this is to run it into the emulator (being software only it should work if it supports every other feature you need in your code)
I'm trying to add some efects to the camera in android,
I found some things on internet but I got stuck when creating the texture,
I use the funcion decodeYUV420SP() that returns me a int[width*height] RGB array with the hex values into each array position,
Now, I want to create an openGL texture of this array but i dont know how, I can convert each hex value to its R_G_B separated and put it into opengl but it doesn't work
I do something like this:
mNewTexture = new int[width*height*4]
for(int i=0; i<mRGB.length; i=i+4){
mNewTexture[i] = getR(mRGB[i]) ; //R
mNewTexture[i+1] = getG(mRGB[i]) ; //G
mNewTexture[i+2] = getB(mRGB[i]) ; //B
mNewTexture[i+3] = getA(mRGB[i]); //A
}
To convert the hex value to RGBA (from 0 to 255)
And i do this to convert it to the openGL texture:
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex);
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, 1024, 512, 0, GL10.GL_RGBA, GL10.GL_FLOAT, FloatBuffer.wrap(mNewTexture));
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
However something is worng, cause it doesn't work...
Any idea?
Why do you try to wrap your int array as a FloatBuffer? Most of your conversions are unnecessary.
Just take your original texture, wrap it in a bytebuffer, and pass it to glTexImage with the type GL_UNSIGNED_BYTE. There's no need to create a new array from what you already have.
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, 1024, 512, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ByteBuffer.wrap(mRGB));
Does anyone know how to point out a given section of the texture buffer array stored in a HW buffer? I'm drawing a triangle strip and filling it with a square image. In my texture I have two square images next to each other, so the texture coordinate buffer points out them out with a total of 16 floats.
With software buffers I'm doing this to access the second image in the texture:
textureCoordinateBuffer.position(8);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureCoordinateBuffer);
With hardware buffers I assumed I do something like this:
// setup HW buffers
// ...
// select HW buffers
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER,vertexCoordinateBufferIndex);
gl11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, textureCoordinateBufferIndex);
// Point out the first image in the texture coordinate buffer
gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
// Draw
// ...
Which works nicely if you want to point out the first image in the texture.
But I would like to access the second image - so I assumed I do this in the last line:
// Point out the second image in the texture coordinate buffer - doesn't work!
gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 8);
But this renders a scewed and discolored image.
Anyone who knows how to to this correctly?
You might want to take a look at the NeHe Android Tutorials. They go into this in detail and show you what you need to do.
Specifically, the lesson you are looking for is here:
http://insanitydesign.com/wp/projects/nehe-android-ports/
Lesson 6
You might not be binding and enabling the buffers, here's a snippet from the tutorial:
public void draw(GL10 gl) {
//Bind our only previously generated texture in this case
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//Set the face rotation
gl.glFrontFace(GL10.GL_CCW);
//Enable the vertex and texture state
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//Draw the vertices as triangles, based on the Index Buffer information
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
Credit: Insanity Design - http://insanitydesign.com/
Edit:
I see what you're asking. Here's more code that should be able to help you then. If you look into the SpriteMethodTest app for android:
http://apps-for-android.googlecode.com/svn/trunk/SpriteMethodTest
You'll notice that Chris Pruett (The developer of this app) shows you the multitude of ways to draw textures to the screen. Below is the code (I believe) you're looking for.
Grid.java
public void beginDrawingStrips(GL10 gl, boolean useTexture) {
beginDrawing(gl, useTexture);
if (!mUseHardwareBuffers) {
gl.glVertexPointer(3, mCoordinateType, 0, mVertexBuffer);
if (useTexture) {
gl.glTexCoordPointer(2, mCoordinateType, 0, mTexCoordBuffer);
}
} else {
GL11 gl11 = (GL11)gl;
// draw using hardware buffers
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
gl11.glVertexPointer(3, mCoordinateType, 0, 0);
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
gl11.glTexCoordPointer(2, mCoordinateType, 0, 0);
gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
}
}
// Assumes beginDrawingStrips() has been called before this.
public void drawStrip(GL10 gl, boolean useTexture, int startIndex, int indexCount) {
int count = indexCount;
if (startIndex + indexCount >= mIndexCount) {
count = mIndexCount - startIndex;
}
if (!mUseHardwareBuffers) {
gl.glDrawElements(GL10.GL_TRIANGLES, count,
GL10.GL_UNSIGNED_SHORT, mIndexBuffer.position(startIndex));
} else {
GL11 gl11 = (GL11)gl;
gl11.glDrawElements(GL11.GL_TRIANGLES, count,
GL11.GL_UNSIGNED_SHORT, startIndex * CHAR_SIZE);
}
}
Specifically, you'll want to look at the code where it takes the false branch of !mUseHardwareBuffers. I suggest you look at the full Grid.java file for a better representation of how to do it because he also sets up the texture pointers and enables OpenGL to start drawing.
On a Side Note: I suggest reading this from Chris also:
http://www.scribd.com/doc/16917369/Writing-Real-Time-Games-for-Android
He goes into what this app does and what he found the most effective way of drawing textures was.