OpenGL es 2.0 glDrawElements index pointer error - android

Im having trouble with texturing a cube with different textures per face. I can draw the cube with one texture on all the faces, but when I try use multiple textures it fails. The way im trying to do it is like so:
//my indexing array located in a header file
#define NUM_IMAGE_OBJECT_INDEX 36
static const unsigned short cubeIndices[NUM_IMAGE_OBJECT_INDEX] =
{
0, 1, 2, 2, 3, 0, // front
4, 5, 6, 6, 7, 4, // right
8, 9,10, 10,11, 8, // top
12,13,14, 14,15,12, // left
16,17,18, 18,19,16, // bottom
20,21,22, 22,23,20 // back
};
now in my rendering function, this currently works for drawing the cube with a single texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, iconTextureID);
glDrawElements(GL_TRIANGLES, NUM_IMAGE_OBJECT_INDEX, GL_UNSIGNED_SHORT, 0);
this does not work
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, iconTextureID);
glDrawElements(GL_TRIANGLES, NUM_IMAGE_OBJECT_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*)&cubeIndices[0]);
which should equate to the same thing, from looking at some other examples. Ultimately I would like to be doing this something like this:
for(int i = 0; i < 6; i++){
iconTextureID = textureID[i];
glBindTexture(GL_TEXTURE_2D, iconTextureID);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLvoid*)&cubeIndices[i*6]); //index 0-5 use texture 1, 6-11 use texture 2, etc
}
does anyone know what could be wrong with this indexing? ive basically copy pasted this code from an android project (which works), currently trying to do this on ios.

In OpenGL ES 2.0, index data can come from either buffer objects or pointers to client memory. Your code is obviously using a buffer object. Though you don't show the creation of this buffer object, where you upload your client array of pointers, or where you call glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) before rendering with it. It must be there or your code would have crashed. When a buffer is bound to GL_ELEMENT_ARRAY_BUFFER, OpenGL expects the "pointer" given to glDrawElements to be a byte offset into the buffer object, not a client-memory pointer.
This is why copy-and-paste coding is a bad idea. Where you copied from was probably using client memory; you are not.
If you want your looping code to work, you need to do the pointer arithmetic yourself:
for(int i = 0; i < 6; i++)
{
iconTextureID = textureID[i];
glBindTexture(GL_TEXTURE_2D, iconTextureID);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(i * 6 * sizeof(GLushort)));
}

Related

Issues combining multiple textures

I am working with multiple particle systems which I am attempting to composite together in a frame buffer to be used in another shader. Each compute shader is working when I run each of them on their own, but something breaks when I attempt to call more than one sequentially. I have tried this many ways so hopefully I am close with at least one of them.
Combining buffers via glBufferSubData:
VBO/VAO
//generate vbo and load data
GLES31.glGenBuffers(1, vbo, 0)
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, vbo[0])
GLES31.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, 4 * (particleCoords.size + particleCoords2.size + particleCoords3.size), null, GLES31.GL_STATIC_DRAW)
GLES31.glBufferSubData(GLES31.GL_SHADER_STORAGE_BUFFER, 0, particleCoords.size * 4, particleCoordBuffer)
GLES31.glBufferSubData(GLES31.GL_SHADER_STORAGE_BUFFER, particleCoords.size * 4, particleCoords2.size * 4, particleCoord2Buffer)
GLES31.glBufferSubData(GLES31.GL_SHADER_STORAGE_BUFFER, (particleCoords.size + particleCoords2.size) * 4, particleCoords3.size * 4, particleCoord3Buffer)
GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 0, vbo[0])
// generate vao
GLES31.glGenVertexArrays(1, vao, 0)
Update positions with compute shader
GLES31.glBindVertexArray(vao[0])
GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, vbo[0])
GLES31.glEnableVertexAttribArray(ShaderManager.particlePositionHandle)
GLES31.glVertexAttribPointer(ShaderManager.particlePositionHandle, COORDS_PER_VERTEX, GLES31.GL_FLOAT, false, COORDS_PER_VERTEX * 4, computeOffsetForIndex(index) / COORDS_PER_VERTEX)//computeOffsetForIndex(index) * 4)
GLES31.glUseProgram(ShaderManager.particleComputeProgram)
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, vbo[0])
GLES31.glUniform1i(ShaderManager.particleTimeHandle, time)
GLES31.glDispatchCompute((sizeForIndex(index) / COORDS_PER_VERTEX) / 128 + 1, 1, 1)
GLES31.glMemoryBarrier(GLES31.GL_ALL_BARRIER_BITS)
// cleanup
GLES31.glBindVertexArray(0)
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0)
GLES31.glDisableVertexAttribArray(ShaderManager.particlePositionHandle)
GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0)
Draw particles
GLES31.glUseProgram(ShaderManager.particleDrawProgram)
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT)
GLES31.glActiveTexture(GLES31.GL_TEXTURE0)
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, snowTexture[0])
GLES31.glUniform1i(ShaderManager.particleTextureHandle, 0)
GLES31.glEnableVertexAttribArray(ShaderManager.particlePositionHandle)
GLES31.glVertexAttribPointer(ShaderManager.particlePositionHandle, COORDS_PER_VERTEX, GLES31.GL_FLOAT, false, COORDS_PER_VERTEX * 4, computeOffsetForIndex(index) / COORDS_PER_VERTEX)
GLES31.glBindVertexArray(vao[0])
GLES31.glDrawArrays(GLES31.GL_POINTS, computeOffsetForIndex(index) / COORDS_PER_VERTEX, sizeForIndex(index) / COORDS_PER_VERTEX)
// cleanup
GLES31.glDisableVertexAttribArray(ShaderManager.particlePositionHandle)
GLES31.glBindVertexArray(0)
GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, 0)
GLES31.glBindTexture(GLES31.GL_TEXTURE0, 0)
onDrawFrame
GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, particleFramebuffer[0])
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, particleFrameTexture[0])
GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA, screenWidth, screenHeight, 0, GLES31.GL_RGBA, GLES31.GL_UNSIGNED_BYTE, null)
GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_LINEAR)
GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MIN_FILTER, GLES31.GL_LINEAR)
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, particleFrameTexture[0], 0)
for (i in 0 until (ShaderManager.particleShaderInfo?.computeIds?.size ?: 0)) {
updateParticles(i)
drawParticles(i)
}
This results in the first particle system animating and drawing as anticipated. Any systems updated after the first do not animate and all draw at (0,0,0). Starting from index 1 has the same results only properly updating the first system and not the remaining. This makes me think something is off when running the shaders one after the other, but seems it shouldn't be an issue as the data from each call is unrelated.
Multiple VBO/VAO
What I thought made the most sense was using a separate VBO/VAO for each system, though it seems I'm missing something when it comes to swapping the bound buffer on the GL_SHADER_STORAGE_BUFFER. This attempt resulted in none of my systems updating correctly. I understand that glVertexAttribPointer only cares about what is currently bound, but perhaps persistence of the changed buffer is lost then?
// generate vbo and load data
GLES31.glGenBuffers(1, vbo, 0)
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, vbo[0])
GLES31.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, 4 * (particleCoords.size), particleCoordBuffer, GLES31.GL_STATIC_DRAW)
GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 0, vbo[0])
// generate vao
GLES31.glGenVertexArrays(1, vao, 0)
//-------2----------
// generate vbo and load data
GLES31.glGenBuffers(1, vbo2, 0)
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, vbo2[0])
GLES31.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, 4 * particleCoords2.size, particleCoord2Buffer, GLES31.GL_STATIC_DRAW)
GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 0, vbo2[0])
// generate vao
GLES31.glGenVertexArrays(1, vao2, 0)
//--------3-----------
// generate vbo and load data
GLES31.glGenBuffers(1, vbo3, 0)
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, vbo3[0])
GLES31.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, 4 * particleCoords3.size, particleCoord3Buffer, GLES31.GL_STATIC_DRAW)
GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 0, vbo3[0])
// generate vao
GLES31.glGenVertexArrays(1, vao3, 0)
The update and draw functions for this approach are the same as above other than the VBO and VAO being swapped out each call for the appropriate objects for the index. I understand that binding a buffer replaces the previous buffer, so perhaps the persisted data is also lost at that point?
Hopefully I'm on the right track, but would welcome a better approach. Thanks for taking a look!
UPDATE
It appears my issue is not actually related to the compute shaders or the data structure being used. It seems the issue actually lies with the sampling of the frame buffer textures and mixing them in the final draw call.
I am currently mixing in a color based on the alpha channel in the frame buffer textures but the output is puzzling. Doing this with each of the three textures successfully adds tex1 and tex2, but not tex3.
outColor = mix(outColor, vec4(1.0), texture2D(tex1, f_texcoord).a);
outColor = mix(outColor, vec4(1.0), texture2D(tex2, f_texcoord).a);
outColor = mix(outColor, vec4(1.0), texture2D(tex3, f_texcoord).a);
Commenting out the mixing of tex1 results in the last two mixes working as expected. This very much confuses me and I'm not sure what the cause could be. Clearly the textures are assigned to the correct indexes as I can access them properly, it's just that I'm unable to add all three. I'm also sampling two other textures in this shader that are working as expected.
Any thoughts would be greatly appreciated!

Starfield optimization in libgdx

I want to create a static starfield in libgdx.
My first way was: create a Decal and a DecalBatch over it.
When I draw the Decal I use a Billboarding technic on the Decal
star.decal.setRotation(camera.direction, camera.up);
next: I wanted to animate the alphas on the decals, so I created on a random way some time:
star.decal.setColor(1, 1, 1, 0.6f+((float) Math.random()*0.4f) );
It is working, but my FPS went down from 55 FPS to 25 FPS (because of my 500-1000 stars)
Can I use only one batch call in any way? Maybe a particleMaterial with only one Vertex list and with a GL_POINT mode that is always face to front of my camera?
How can I do this in libgdx?
The Batch is way to complex than what you need , on every frame it needs to copy all the vertices of the sprites in another array and do calculations on them to find the scale rotation etc..
As you suspect GL_POINT sprites will be way faster and in a medium range device it should be able to render in 60 fps like 2000 points that have different position and color
here is some old code of mine ,its in c and it uses opengl es 1.1 and propably there will be a more simple way to do it in libgdx
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnable (GL_POINT_SPRITE_OES);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TXTparticle);
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
glPointSize(30);
glColorPointer(4, GL_FLOAT, 32, particlesC);//particlesC the vertices color
glVertexPointer(3, GL_FLOAT, 24, particlesV);//particlesV the vertices
glDrawArrays(GL_POINTS, 0, vertvitLenght/6);
glDisable( GL_POINT_SPRITE_OES );
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

GL_LUMINANCE with byte array on OpenGL ES 2.0

I'm programming combining the yuv data which were got by libvpx(WebM decode library) and OpenGL ES 2.0 shader(for Android).
These are the same byte array, but it's not drawn correctly in this case.
Success:
// ex) unsigned char *p = yuv.y, yuv.u or yuv.v;
for(int dy = 0; dy < hh; dy++){
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, dy, ww, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE, p);
p += ww;
}
Fail :
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ww, hh, GL_LUMINANCE, GL_UNSIGNED_BYTE, p);
Because I'm not knowledgeable about OpenGL, I don't understand this reason.
I think that if glTexSubImage2D is called for each line, performance will get worse. Isn't it improvable any more?
My best guess is that the data you are passing to glTexSubImage2D is not correctly aligned.
From the glTexSubImage2D Reference page for OpenGL ES 2.0:
Storage parameter GL_UNPACK_ALIGNMENT, set by glPixelStorei, affects the way that data is read out of client memory. See glPixelStorei for a description.
Passing a single line at a time from your data probably hides the fact that each line is not correctly aligned, and therefore the call succeeds.

How to draw/render a Bullet Physics collision body/shape?

I have implemented the Bullet Physics engine into my android program with the NDK (I am using Vuforia's imagetarget example for android), and it is set up and working correctly, however I would like to render/draw my collision boxes/planes to see my rigid bodies (btRigidBody)/collision shapes (btCollisionShape), I'm positive this is possible but I can't find any tutorials on how to do it!
I have taken the hello world Bullet physics tutorial on their wiki page and modified it to apply the transformations from the falling physics body to a 3d object I have in opengl es 2.0 to view the collision bodies, here is the code I am using to render to object:
void drawRigidBody(btRigidBody* body,QCAR::Matrix44F modelViewMatrix, unsigned int textureID)
{
btTransform trans;
body->getMotionState()->getWorldTransform(trans);
LOG("sphere pos: (x %f , y %f, z %f)",trans.getOrigin().getX(),trans.getOrigin().getY(),trans.getOrigin().getZ());
float physicsMatrix[16];
trans.getOpenGLMatrix(physicsMatrix);
SampleUtils::scalePoseMatrix(kObjectScale, kObjectScale, kObjectScale,
&modelViewMatrix.data[0]);
QCAR::Matrix44F modelViewProjection, objectMatrix;
SampleUtils::multiplyMatrix(&modelViewMatrix.data[0], physicsMatrix, &objectMatrix.data[0]);
SampleUtils::multiplyMatrix(&projectionMatrix.data[0], &objectMatrix.data[0], &modelViewProjection.data[0]);
glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &signVerts[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &signNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &signTexCoords[0]);
glEnableVertexAttribArray(vertexHandle);
glEnableVertexAttribArray(normalHandle);
glEnableVertexAttribArray(textureCoordHandle);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE,
(GLfloat*)&modelViewProjection.data[0] );
glDrawArrays(GL_TRIANGLES, 0, signNumVerts);
}
EDIT: looking at the code for btBoxShape i noticed you can grab the box vertices and normals:
btVector3** vertices= wallShape->getVertices();
btVector3**normals = wallShape->getNormals();
but you can't grab a list of indices to draw the vertex points in a certain order!
If I recall correctly, this is not the proper way to draw debug shapes in Bullet. Did you read the user manual (PDF), page 16?
You are supposed to implement your own debug drawer class which implements btIDebugDraw, and in this class you implement the drawLine method.
You pass this debug drawer to bullet with setDebugDrawer, and then enable it with world->getDebugDrawer->setDebugMode(debugMode);
To draw the world, call world->debugDrawWorld();
This then calls drawLine on your custom function numerous times until a wireframe model of the physics world has been drawn.

Can't draw loaded models in OpenGL ES 1.x with C++

I load obj models and try to render them with OpenGL ES using Android NDK:
class ObjModel{
public:
ObjModel();
~ObjModel();
int numVertex, numNormal,numTexCoord, numTriange;
float *vertexArray;
float *normalArray;
float *texCoordArray;
unsigned short *indexArray;
void loadModel(string fileName);
};
model->loadModel(filename);
glVertexPointer(3, GL_FLOAT, 0, &(model->vertexArray[0]));
glNormalPointer(GL_FLOAT, 0, &(model->normalArray[0]));
glDrawElements(GL_TRIANGLES, model->numTriange, GL_UNSIGNED_SHORT,
&(model->indexArray[0]));
Model is not rendered fully, I see only part of it.
I checked the data in arrays and they are parsed properly. I think that the only issue might be with passing arguments. Am I doing it right?
Hope this helps! I think you are just missing the number 3!
glDrawElements(GL_TRIANGLES, 3 * model->numTriange, GL_UNSIGNED_SHORT,
&(model->indexArray[0]));

Categories

Resources