I'm trying to render a scene using OpenGL ES 2.0 in an Android App, however, the screen keeps being drawn with the defined clear color.
I had success rendering simpler examples, but I'm failing when using packed vertex buffer.
The idea is to render a scene with a camera inside a Sphere, here are some code snippets which should give some context and also is where I think the bug is.
Fragment Shader:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 vTextureCoord;
uniform inputImageTexture;
void main()
{
vec4 color = texture2D(inputImageTexture, vTextureCoord);
gl_FragColor = vec4(1.0);
}
Vertex Shader:
uniform mat4 uMVPMatrix;
uniform mat4 uTransform;
attribute vec4 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord;
void main()
{
gl_Position = uMVPMatrix * aPosition * vec4(1, -1, 1, 1);
vec4 coord = (aTextureCoord / 2.0) + 0.5;
vTextureCoord = (uTransform * coord).xy;
}
The GL program initialization:
mProgram = new ProgramObject();
if(mProgram.init(vsh, fshResult)) {
GLES20.glClearColor(1.0f, 0.f, 0.f, 1.f);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDisable(GLES20.GL_CULL_FACE);
uMVPMatrixLocation = mProgram.getUniformLoc("uMVPMatrix");
aPositionLocation = mProgram.attributeLocation("aPosition");
aTextureCoordLocation = mProgram.attributeLocation("aTextureCoord");
mTransformLoc = mProgram.getUniformLoc("uTransform");
}
Vertex loading:
sphere = new Sphere(SPHERE_SLICES, 0.f, 0.f, 0.f, SPHERE_RADIUS, SPHERE_INDICES_PER_VERTEX);
mProgram.bind();
final int buffers[] = new int[1];
GLES20.glGenBuffers(1, buffers, 0);
mVertexBuffer = buffers[0];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, sphere.getVerticesSize(), sphere.getVertices(), GLES20.GL_STATIC_DRAW);
Render:
GLES20.glViewport(viewport.x, viewport.y, viewport.width, viewport.height);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(TEXTURE_2D_BINDABLE, texID);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
GLES20.glVertexAttribPointer(aPositionLocation, 3,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), sphere.getVertices());
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aTextureCoordLocation);
GLES20.glVertexAttribPointer(aTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(),
sphere.getVertices().duplicate().position(3));
Matrix.multiplyMM(pvMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
Matrix.multiplyMM(mvpMatrix, 0, pvMatrix, 0, modelMatrix , 0);
GLES20.glUniformMatrix4fv(uMVPMatrixLocation, 1, false, mvpMatrix, 0);
for (int j = 0; j < sphere.getNumIndices().length; ++j) {
GLES20.glDrawElements(GLES20.GL_TRIANGLES, sphere.getNumIndices()[j], GLES20.GL_UNSIGNED_SHORT, sphere.getIndices()[j]);
}
Any insights are welcome, thank you very much.
Update
The could was running without any errors on a Galaxy S6, but, now running on a One Plus X I'm getting the following error:
<gl_draw_error_checks:598>: GL_INVALID_OPERATION
glDrawElements: glError 0x502
After running:
for (int j = 0; j < sphere.getNumIndices().length; ++j) {
GLES20.glDrawElements(GLES20.GL_TRIANGLES, sphere.getNumIndices()[j], GLES20.GL_UNSIGNED_SHORT, sphere.getIndices()[j]);
}
You're mixing up two ways of using vertex arrays:
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
...
GLES20.glVertexAttribPointer(aPositionLocation, 3,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), sphere.getVertices());
In ES 2.0, there are two ways of using vertex arrays:
Client-side vertex arrays.
Vertex-buffer objects (VBOs).
With client-side vertex arrays, you don't store your vertex data in VBOs, but pass the vertex data directly as the last argument to the glVertexAttribPointer() call. In C/C++ bindings, this is a pointer to the data, in the Java bindings it's a Java Buffer object.
When using VBOs, you store your vertex data in a VBO, using glBufferData(). Then you bind the VBO before the glVertexAttribPointer() call, and pass the offset of the data relative to the start of the VBO as the last argument.
In your example:
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
GLES20.glVertexAttribPointer(aPositionLocation, 3,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aTextureCoordLocation);
GLES20.glVertexAttribPointer(aTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), 12);
Note that the offset is in bytes, so it's 12 bytes if your colors are offset by 3 floats relative to the positions.
Client-side vertex arrays are deprecated, and partly unavailable, in newer versions of OpenGL. So storing the data in VBOs, as you already are, is the right way to go.
Related
As I did not find success in drawing multiple triangles with different matrices for each, for now I am stuck with transforming vertices on CPU and use a shader without matrix transformation..
Help will be greatly appreciated !
Here is my current shader :
attribute vec2 vertices;
attribute vec2 textureUvs;
varying vec2 textureUv;
void main()
{
gl_Position = vec4(vertices,0.0,1.0);
textureUv = textureUvs;
};
It works very well except that all vertices are transformed by the CPU before calling OpenGL drawArray(),I suppose that I will get better performance if I can send each triangles matrix and let OpenGL compute vertices.
And here is the draw call :
public final static void drawTexture(FloatBuffer vertices, FloatBuffer textureUvs, int textureHandle, int count, boolean triangleFan)
{
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle);
GLES20.glUseProgram(progTexture);
GLES20.glEnableVertexAttribArray(progTextureVertices);
GLES20.glVertexAttribPointer(progTextureVertices, 2, GLES20.GL_FLOAT, false, 2*Float.BYTES, vertices);
GLES20.glEnableVertexAttribArray(progTextureUvs);
GLES20.glVertexAttribPointer(progTextureUvs, 2, GLES20.GL_FLOAT, false, 2*Float.BYTES, textureUvs);
if(triangleFan)
{
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4 * count); //Faster 10%
}
else
{
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6 * count);
}
GLES20.glDisableVertexAttribArray(progTextureVertices);
GLES20.glDisableVertexAttribArray(progTextureUvs);
}
Note that it is a Sprite renderer that's why I used only 2d vertices.
I finally answered my own question, and yes it is possible to draw mutiple triangles with differents matrices with OpenGLES2 and it worth it !
The answer is related to this one How to include model matrix to a VBO? and #httpdigest comment.
Basically for sprites it only reqiere two vec3 as attributes of the shader that you fill with first and second row of your matrix 3x3.
Here is the shader I am using :
attribute vec3 xTransform;
attribute vec3 yTransform;
attribute vec2 vertices;
attribute vec2 textureUvs;
varying vec2 textureUv;
void main()
{
gl_Position = vec4(dot(vec3(vertices,1.0), xTransform), dot(vec3(vertices,1.0), yTransform), 0.0,1.0) ;
textureUv = textureUvs;
}
First you get two attributes pointers :
int progTextureXTransform = GLES20.glGetAttribLocation(progTexture, "xTransform");
int progTextureYTransform = GLES20.glGetAttribLocation(progTexture, "yTransform");
And for drawing you pass one vector of each per vertex :
GLES20.glEnableVertexAttribArray(progTextureXTransform);
GLES20.glVertexAttribPointer(progTextureXTransform, 3, GLES20.GL_FLOAT, false, 3*Float.BYTES, xTransforms);
GLES20.glEnableVertexAttribArray(progTextureYTransform);
GLES20.glVertexAttribPointer(progTextureYTransform, 3, GLES20.GL_FLOAT, false, 3*Float.BYTES, yTransforms);
On a galaxy Tab 2 this is twice faster than computing vertices with CPU.
xTransform is the first row of your 3x3 matrix
yTransform is the second row of your 3x3 matrix
And of course this can be extended for 3d rendering by adding a zTransform + switch to vec4
I have been stuck all day yesterday with this problem and cant figure it out. The code is below but generally i am trying to give a mesh Vertex Attributes for 1.Postions 2.Indices 3.Normals and 4.a single float value.
The values are all stored in different VBOs and after binding each vbo i declare the vertexAttribPointer. I cant get both normals and float value working. What im seeing seems like the position of the float value is either the x y or z part of the normals vec3 in the previous vbo.
GL4 gl = GLContext.getCurrentGL().getGL4();
int[] vaoids = new int[1];
gl.glGenVertexArrays(1,vaoids,0);
int[] vboids = new int[4];
gl.glGenBuffers(4,vboids,0);
gl.glBindVertexArray(vaoids[0]);
FloatBuffer verticesBuffer = FloatBuffer.allocate(mesh.vertices.length);
verticesBuffer.put(mesh.vertices);
verticesBuffer.flip();
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboids[0]);
gl.glBufferData(gl.GL_ARRAY_BUFFER, mesh.vertices.length * 4 ,verticesBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, false, 0, 0);
verticesBuffer.clear();
verticesBuffer = null;
//normal buffer
FloatBuffer normalBuffer = FloatBuffer.allocate(mesh.normals.length);
normalBuffer.put(mesh.normals);
normalBuffer.flip();
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboids[2]);
gl.glBufferData(gl.GL_ARRAY_BUFFER, mesh.normals.length * 4 ,normalBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(2);
gl.glVertexAttribPointer(2, 3, gl.GL_FLOAT, false, 0, 0);
normalBuffer.clear();
normalBuffer = null;
//color buffer
float[] colors = new float[mesh.vertices.length/3];
Arrays.fill(colors,255.0f);
FloatBuffer colorBuffer = FloatBuffer.allocate(colors.length);
colorBuffer.put(colors);
colorBuffer.flip();
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboids[3]);
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors.length * 4 ,colorBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(3);
gl.glVertexAttribPointer(3, 1, gl.GL_FLOAT,false, 0, 0);
colorBuffer.clear();
colorBuffer = null;
IntBuffer indicesBuffer = IntBuffer.allocate(mesh.indices.length);
indicesBuffer.put(mesh.indices);
indicesBuffer.flip();
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, vboids[1]);
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, mesh.indices.length * 4 ,indicesBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(1);
gl.glVertexAttribPointer(1, mesh.type.equals(MeshType.TRIANGLE) ? 3 : mesh.type.equals(MeshType.LINE) ? 2 : mesh.type.equals(MeshType.POINT) ? 1:0, gl.GL_UNSIGNED_INT, false, 0, 0);
indicesBuffer.clear();
indicesBuffer = null;
//gl.glBindBuffer(gl.GL_ARRAY_BUFFER,0);
gl.glBindVertexArray(0);
This the code that declares the vao and vbos. I render with glDrawElements and enable the needed VertexAttributeArray Indices before that. In my Shader I access the value as following:
layout (location=0) in vec3 position;
layout (location=2) in vec3 normal;
layout (location=3) in float color;
out vec3 normals;
out vec4 positionWorldSpace;
out flat float vertexColor;
And the fragment shader
in flat float color;
I can get both of them working separate but if i declare both they float values are not correct anymore. The normals seems to be right however. As i said the values in the float seem the be values from the normals. Can there be some sort of overflow from the normal vbo to the float vbo? After hours of looking at the code i just cant spot the error.
The indices are not attributes. The [Index buffer](Index buffers) (GL_ELEMENT_ARRAY_BUFFER) is stated in the VAO directly. See Vertex Specification.
When you use glDrawArrays then the order vertex coordinates of the vertex coordinates in the array defines the primitives. If you want to use a different order or you want to use vertices for different primitives, then you have to use glDrawElements. When you use glDrawElements, then the primitives are defined by the vertex indices in the GL_ELEMENT_ARRAY_BUFFER buffer:
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, vboids[1]);
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, mesh.indices.length * 4 ,indicesBuffer,gl.GL_STATIC_DRAW);
// DELETE
//gl.glEnableVertexAttribArray(1);
//gl.glVertexAttribPointer(1, mesh.type.equals(MeshType.TRIANGLE) ? 3 : mesh.type.equals(MeshType.LINE) ? 2 : mesh.type.equals(MeshType.POINT) ? 1:0, gl.GL_UNSIGNED_INT, false, 0, 0);
indicesBuffer.clear();
indicesBuffer = null;
gl.glBindVertexArray(0);
gl.glDrawElements(gl.GL_TRIANGLES, mesh.indices.length, gl.GL_UNSIGNED_INT, null);
I am attempting implementing shadows in my OpenGL scene. However, in my shader, whenever I try to access the texture value in the shadow map (that I rendered previously), I always get 1, or a value close to 1, for the x, y, z, and w values.
The problem is that I thought these values are supposed to represent the z coords of the respective fragment in the shadow map/texture (from the sun's perspective).
The relevant initiation code (in JOGL):
gl.glEnable(GL2.GL_TEXTURE_2D);
// generate stuff
IntBuffer ib = IntBuffer.allocate(1);
gl.glGenFramebuffers(1, ib);
depthMapFBO = ib.get(0);
ib = IntBuffer.allocate(1);
gl.glGenTextures(1, ib);
depthMap = ib.get(0);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, depthMapFBO);
gl.glBindTexture(GL2.GL_TEXTURE_2D, depthMap);
gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_DEPTH_COMPONENT16, 1024, 1024, 0, GL2.GL_DEPTH_COMPONENT, GL2.GL_FLOAT, null);
// prevents 'shadow acne'
gl.glPolygonOffset(2.5f, 0);
// prevents multiple shadows
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
// prevents (or expects!!!) pixel-y textures
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
// store one value in all four components of pixel
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY);
The relevant draw/per-frame code:
// render shadows
gl.glUseProgram(shadowProgram);
gl.glUniformMatrix4fv(lightMatrixLocShadow, 1, false, lightMatrix.getMatrix(), 0); // yep (haha change viewMatrix -> lightMatrix)
gl.glUniformMatrix4fv(projMatrixLocShadow, 1, false, projMatrix.getMatrix(), 0);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, depthMapFBO);
gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, GL2.GL_DEPTH_ATTACHMENT, GL2.GL_TEXTURE_2D, sha.depthMap, 0);
gl.glDrawBuffer(GL2.GL_NONE);
gl.glReadBuffer(GL2.GL_NONE);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
gl.glViewport(0, 0, 1024, 1024);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, depthMapFBO);
gl.glClear(GL2.GL_DEPTH_BUFFER_BIT);
renderScene(gl, sunMatrix);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
// render display (regular)
gl.glUseProgram(displayProgram);
gl.glDrawBuffer(GL2.GL_FRONT);
gl.glReadBuffer(GL2.GL_FRONT);
gl.glUniformMatrix4fv(viewMatrixLoc, 1, false, viewMatrix.getMatrix(), 0);
gl.glUniformMatrix4fv(projMatrixLocDisplay, 1, false, projMatrix.getMatrix(), 0);
gl.glUniformMatrix4fv(lightMatrixLocDisplay, 1, false, lightMatrix.getMatrix(), 0);
gl.glUniform4fv(sunPositionLoc, 1, sunWorldPosition, 0); // send sun's position to shader
gl.glUniform1f(sunBrightnessLoc, sunBrightness);
gl.glUniform1i(shadowMapLoc, 0);
gl.glViewport(0, 0, screenWidth, screenHeight);
//gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, depthMapFBO);
// day-night cycle
float[] color = SkyManager.getSkyColor(time);
gl.glClearColor(color[0], color[1], color[2], 1);
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glActiveTexture(GL2.GL_TEXTURE0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, sha.depthMap);
//gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
renderScene(gl, sunMatrix);
The relevant fragment shader code (used to debug the values; in glsl 1.3)
gl_FragColor = vec4(vec3(texture2D(shadowMap, lightProjPosition.xy).z), 1.0);
The expected values from the texture() call are, of course, the different distances of the fragments to the light source.
If anyone can find out why I am getting 1 I would appreciate the help.
EDIT
Here is the shadow shader code:
Vertex:
#version 130
uniform mat4 light;
uniform mat4 proj;
out vec4 position;
void main() {
position = proj * light * gl_Vertex;
gl_Position = position;
}
Fragment:
#version 130
in vec4 position;
void main() {
gl_FragColor.z = position.z; // still doesn't work with this line commented
}
I have just tried switching to use Interleaved VBOs. I have stepped through the process of creating the Interleaved VBO and it appears that it has the correct information init.
VVV NNN TT etc.
Here is the code for initialising the buffer
VertexBuffer = Loader.vertexBuffer;
final int buffers[] = new int[1];
GLES20.glGenBuffers(1, buffers, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, VertexBuffer.capacity(), VertexBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
mBufferIdx = buffers[0];
VertexBuffer.limit(0);
VertexBuffer = null;
and here is my code for drawing the model
final int stride = (mPositionDataSize + mNormalDataSize + mTextureCoordinateDataSize) * mBytesPerFloat;
// Pass in the position information
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBufferIdx);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, stride, 0);
// Pass in the normal information
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBufferIdx);
GLES20.glEnableVertexAttribArray(mNormalHandle);
GLES20.glVertexAttribPointer(mNormalHandle, mNormalDataSize, GLES20.GL_FLOAT, false, stride, mPositionDataSize * mBytesPerFloat);
// Pass in the texture information
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBufferIdx);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false,
stride, (mPositionDataSize + mNormalDataSize) * mBytesPerFloat);
// Clear the currently bound buffer (so future OpenGL calls do not use this buffer).
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
// Draw .
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, NumVertices);
I left the matrices work out as this worked before using VBOs and i am seeting all the handles correctly.
My app appears to run as if the models are there but just invisible. for example i am moving a model and being told when it gets to a certain position, i just cant see it like i did before i moved to VBOs.
Let me know if i need to upload anything else. Any advice would be appreciated.
UPDATE!
I think the issue maybe in the way i create the interleaved VBO here is the code
private void createVertexBuffer(float[] VertexList, float[] NormalList, float[] TextureList)
{
final int vertexDataSize = VertexList.length + NormalList.length + TextureList.length;
this.vertexBuffer = ByteBuffer.allocateDirect(vertexDataSize * mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();
int PositionOffset = 0;
int NormalOffset = 0;
int TextureOffset = 0;
for(int i = 0; i < NumVerts; i++)
{
this.vertexBuffer.put(VertexList, PositionOffset, mPositionDataSize);
PositionOffset += mPositionDataSize;
this.vertexBuffer.put(NormalList, NormalOffset, mNormalDataSize);
NormalOffset += mNormalDataSize;
this.vertexBuffer.put(TextureList, TextureOffset, mTextureCoordinateDataSize);
TextureOffset += mTextureCoordinateDataSize;
}
this.vertexBuffer.position(0);
}
What could i be doing wrong?
UPDATE CODE
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix");
mLightPosHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_LightPos");
//mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color");
Cube1.mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
Cube1.mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
Cube1.mNormalHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Normal");
Cube1.mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
Cube1.SetTexture();
Cube1.SetIdentity();
Cube1.SetPosition();
Cube1.SetScale(10.0f, 10.0f, 10.0f);
Cube1.SetRotation(RotationAngle, 0.0f, 0.0f, 1.0f);
Cube1.DrawModel(mProjectionMatrix, mViewMatrix, mMVPMatrix, mMVPMatrixHandle, mMVMatrixHandle, mLightPosHandle, mLightPosInEyeSpace);
public void SetTexture()
{
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(mTextureUniformHandle, 0);
}
I am not sure what my issue was in the above code how ever i re wrote my code to use an index buffer and have submitted in another question. Found here
Along with the answer i gave in the other question it should give a clear way of introducing VBO's and IBO's for any one who is struggling
I am trying to switch to VBOs, without indices for now. But all I get is just a blank screen. Can someone point out why it is blank? The same code works fine if I comment out the vbo-specific code and replace 0(offset) in glVertexAttribPointer by mFVertexBuffer, i.e without using VBOs.
This is my onDraw method
GLES20.glClearColor(0.50f, 0.50f, 0.50f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
// Bind default FBO
// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id);
int vertexCount = mCarVerticesData.length / 3;
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
checkGlError("1");
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT,false, 0, 0);
checkGlError("2");
GLES20.glEnableVertexAttribArray(positionHandle);
checkGlError("3 ");
transferTexturePoints(getTextureHandle());
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
checkGlError("glDrawArrays");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisable(GLES20.GL_BLEND);
This is my vbo setup:
// Allocate and handle vertex buffer
ByteBuffer vbb2 = ByteBuffer.allocateDirect(mCarVerticesData.length
* FLOAT_SIZE_BYTES);
vbb2.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb2.asFloatBuffer();
mFVertexBuffer.put(mCarVerticesData);
mFVertexBuffer.position(0);
// Allocate and handle vertex buffer
this.buffers = new int[1];
GLES20.glGenBuffers(1, buffers, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mFVertexBuffer.capacity()
* FLOAT_SIZE_BYTES, mFVertexBuffer, GLES20.GL_STATIC_DRAW);
Before linking my program:
GLES20.glBindAttribLocation(program, 0, "aPosition");
checkGlError("bindAttribLoc");
And my vertex shader is :
uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec2 aTextureCoordinate;
varying vec2 v_TextureCoordinate;
void main()
{
gl_Position = uMVPMatrix * aPosition;
v_TextureCoordinate = aTextureCoordinate;
gl_PointSize= 10.0;
}
You need to also generate an elements array and call something like this in order to render your "object":
// Bind the vertex buffer
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, _bufferIds.get(2));
GLES20.glVertexAttribPointer(4, 4, GLES20.GL_FLOAT, false, 4*4, 0);
// Bind the elements buffer and draw it
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, _bufferIds.get(1));
GLES20.glDrawElements(GLES20.GL_TRIANGLES, _numElements, GLES20.GL_UNSIGNED_SHORT, 0);
Hope that helps.
I solved the problem by rewriting the way I was uploading vertices data. I was modifying it and so, I needed to call glBindBufferData again for it to be uploaded. And I was able to use VBOs without using glDrawElements and indices, and it works well.