Draw multiple objects in one glDrawElements() - android

I'm practicing in basic things in OpenGL ES2.0 using this 2d tutorial:
http://androidblog.reindustries.com/a-real-opengl-es-2-0-2d-tutorial-part-2/
Basically it just draws a rect with a texture.
Now I would like to draw multiple rects in one glDrawElements() call on different positions but with the same texture. So I add more items to the vertices and indices arrays. However texture coords (uvs array) are the same for every rect and there's no sense to stretch it by copying the same values. Can I somehow reuse it or perhaps set it as a constant somewhere inside the shader code?
Vertex shader:
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main() {
gl_Position = uMVPMatrix * vPosition;
v_texCoord = a_texCoord;
}
Fragment shader:
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main() {
gl_FragColor = texture2D( s_texture, v_texCoord );
}
Arrays (used in buffers):
vertices = new float[]
{ 10.0f, 200f, 0.0f,
10.0f, 100f, 0.0f,
100f, 100f, 0.0f,
100f, 200f, 0.0f,
};
indices = new short[] {0, 1, 2, 0, 2, 3};
uvs = new float[] {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
Render code:
private void Render() {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
int mPositionHandle = GLES20.glGetAttribLocation(program, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
int mTexCoordLoc = GLES20.glGetAttribLocation(program, "a_texCoord" );
GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, uvBuffer);
int mtrxhandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
int mSamplerLoc = GLES20.glGetUniformLocation (program, "s_texture" );
GLES20.glUniform1i ( mSamplerLoc, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
}

Related

VBO, Shader C++ Android Confusion

I'm having trouble understanding where/how to setup buffers for a native android application in VS 2015. I apologize if this isn't the best way to ask a question. I appreciate any help/insight.
This is what I have so far:
(in engine_init_display)
GLint vShaderLength = vertex_shader.length();
const GLchar* vcode = vertex_shader.c_str();
GLint fShaderLength = fragment_shader.length();
const GLchar* fcode = fragment_shader.c_str();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vcode, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fcode, NULL);
glCompileShader(fs);
shader_programme = glCreateProgram();
glAttachShader(shader_programme, fs);
glAttachShader(shader_programme, vs);
glLinkProgram(shader_programme);
GLint pos_id = glGetAttribLocation(shader_programme, "position");
//Set vertex data
glUseProgram(shader_programme);
glVertexAttribPointer(pos_id, 0, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(pos_id, //GLuint
3, //GLint size
GL_FLOAT, //GLenum type
GL_FALSE, //GLboolean
(sizeof(float) * 5), //GLsizei stride
points //const GLvoid *pointer
);
glEnableVertexAttribArray(pos_id);
(in engine_draw_frame)
glClearColor(1.0f, 0.41f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
eglSwapBuffers(engine->display, engine->surface);
With this, I get a pink (clear colour) background. I'm not sure what I'm doing wrong.
Here are my vertex data and shaders
float points[] =
{
-0.2f, 0.6f, 0.0f,
0.0f, 1.0f,
0.5f, 0.5f, 0.0f,
1.0f, 1.0f,
-0.5f, -0.5f, 0.0f,
0.0f, 0.0f,
0.5f, -0.5f, 0.0f,
1.0f, 0.0f
};
unsigned short indices[] =
{
0, 2, 1, 2, 3, 1
};
std::string vertex_shader =
"#version 300 es \n"
"in vec3 position; \n"
"void main () { \n"
" gl_Position = vec4 (position, 1.0); \n"
"} \n";
std::string fragment_shader =
"#version 300 es \n"
"precision highp float; \n"
"out vec4 frag_colour; \n"
"void main () { \n"
" frag_colour = vec4 (0.5, 0.0, 0.5, 1.0); \n"
"} \n";
OK, I figured it out. There isn't anything wrong with my shaders or vertex array. The problem was that I didn't specify EGL to create an OpenGLES2 context using EGL_CONTEXT_CLIENT_VERSION.
Check here -> Khronos Specification, page 43 (of pdf) for more info
Sample from specification:
EGLContext eglCreateContext(EGLDisplay dpy,
EGLConfig config, EGLContext share_context,
const EGLint *attrib_list);
if the *attrib_list is left null, the default is OpenGLES1 and shaders will not work in that context.
So, what you need to do is create an attribute list. Something along the lines of:
EGLint contextAttributes[]=
{
EGL_CONTEXT_CLIENT_VERSION,2,
EGL_NONE
}
and pass that to the create context
p_context = eglCreateContext(display, config, NULL, contextAttributes);
Basically, I was too unsure of my ability with vertex buffers that I focused on that for a long time.

Does not translate well - Android - OpenGL ES 2

I have this code that should move my circle( square):
float[] scratch = new float[16];
float[] move = new float[16];
Matrix.setIdentityM(move, 0);
Matrix.translateM(move, 0, 100, 100, 0);
Matrix.multiplyMM(scratch, 0, projectionMatrix, 0, move, 0);
mCircle.draw(scratch);
projectionMatrix is the camera:
Matrix.orthoM(projectionMatrix, 0, 0, width, height, 0, -1f, 1f);
But when I execute the code I get this:
Image
I followed the code from Android Developer.
precision highp float;
uniform float uRadius;
vec2 center = vec2(uRadius, uRadius);
vec2 coord = vec2(gl_FragCoord.x, 1080. - gl_FragCoord.y);
vec2 position = coord - center;
uniform vec4 uColor;
void main()
{
if (length(position) > uRadius) {
discard;
}
gl_FragColor = uColor;
}
--------------------------------
uniform mat4 uMatrix;
attribute vec4 aPosition;
void main()
{
gl_Position = uMatrix * aPosition;
}
My main loop:
public void onDrawFrame(GL10 unused) {
// Draw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
float[] scratch = new float[16];
float[] move = new float[16];
Matrix.setIdentityM(move, 0);
Matrix.translateM(move, 0, 50, 50, 0);
Matrix.multiplyMM(scratch, 0, projectionMatrix, 0, move, 0);
mCircle.draw(scratch);
}
And circle draw functions is:
public void draw(float[] projectionMatrix) {
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
int mColorHandle = GLES20.glGetUniformLocation(mProgram, "uColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, mColor, 0);
int radiusHandle = GLES20.glGetUniformLocation(mProgram, "uRadius");
MyGLRenderer.checkGlError("glGetUniformLocation");
GLES20.glUniform1f(radiusHandle, mRadius);
// get handle to shape's transformation matrix
int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, projectionMatrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
// Draw the square
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
After some hours I finally found the logical error in the fragment shader: the center of the circle was remaining the same, now I added 2 more uniforms for the offsets/position and it's working.

Android OpenGLES Brown square

So I'm trying to learn openGLES 2.0 and create a textured rectangle. Apparently I didn't follow all the instructions and now I've ended up with just a odd color square.
heres my shaders.
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "attribute vec2 a_TexCoordinate;\n" // Per-vertex texture coordinate information we will pass in.
+ "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in.
// + "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in.
// + "varying vec4 v_Color; \n" // This will be passed into the fragment shader.
+ "varying vec2 v_TexCoordinate; \n" // This will be passed into the fragment shader.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
+ " v_TexCoordinate = a_TexCoordinate;\n" // Pass the texture coordinate through to the fragment shader.
// It will be interpolated across the triangle.
+ " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position.
+ " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in
+ "} \n";
final String fragmentShader =
"precision mediump float; \n" // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "uniform sampler2D u_Texture; \n" // The input texture.
+ "uniform vec4 u_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "varying vec2 v_TexCoordinate; \n" // Interpolated texture coordinate per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = texture2D(u_Texture, v_TexCoordinate); \n"
+ "} \n";
Here is the load texture function
public static int loadTexture(final Context context, final int resourceId)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
And here is the drawFrame
#Override
public void onDrawFrame(GL10 gl) {
// Set the background clear color to gray.
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
mTextureUniformHandle = GLES20.glGetUniformLocation(programHandle, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(programHandle, "a_TexCoordinate");
// Set the active texture unit to texture unit 0.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// 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);
// Draw the triangle facing straight on.
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, Fields.screen_width / 2, Fields.screen_height / 2, 0);
Matrix.scaleM(mModelMatrix, 0, Fields.screen_width / 4, Fields.screen_width / 4, 0);
drawTriangle(mTriangle1Vertices);
}
Any advice for getting rid of the wierd brown square and actually displaying the texture?
Edit: Here are the texture coordinates
public GL20Renderer(Context context) {
final float[] triangle1VerticesData = {
// X, Y, Z,
// R, G, B, A
-1f, 1f, 0.0f,
-1, -1, 0.0f,
1f, 1f, 0.0f,
-1f, -1f, 0.0f,
1f, -1f, 0.0f,
1f, 1f, 0.0f,
};
// Initialize the buffers.
mTriangle1Vertices = ByteBuffer.allocateDirect(triangle1VerticesData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangle1Vertices.put(triangle1VerticesData).position(0);
final float[] triangle1TextureCoordinateData =
{
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
mTriangleTextureCoordinates = ByteBuffer.allocateDirect(triangle1TextureCoordinateData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleTextureCoordinates.put(triangle1TextureCoordinateData).position(0);
this.context = context;
}
and here is the drawtriangle function
private void drawTriangle(final FloatBuffer aTriangleBuffer)
{
// Pass in the position information
aTriangleBuffer.position(mPositionOffset);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
int colorHandle = GLES20.glGetUniformLocation(programHandle, "u_Color");
// Set color for drawing the triangle
GLES20.glUniform4f(colorHandle, 0.0f, 0.8f, 1.0f, 1.0f);
// This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
Your drawTriangle code doesn't set the texture co-ordinates anywhere. Add some code something like this:
triangle1TextureCoordinateData.position(mPositionOffset * 2 / 3);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false,
0, triangle1TextureCoordinateData);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
Note you can set the stride to zero if your data is packed in the buffer.

Background image move OpenGL ES2

I'm trying to get my 2D-background image moving. In the fututre it will be implemented as automatic movement (looks like camera follow some object). A typical example - angry birds game. Camera follows the bird during attack.
Currently, I just change the values in setLookAtM(). Here is the code:
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,GLES20.GL_ONE_MINUS_SRC_ALPHA);
// background
bg = new BackGround(mActivityContext);
}
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setLookAtM(mVMatrix, 0, -1f, 0f, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.setIdentityM(mTrMatrix, 0);
bg.draw(mMVPMatrix);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width , height );
float ratio = (float) width / height;
Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
class BackGround {
private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
static final int COORDS_PER_VERTEX = 3;
static float squareCoords[] = { -15.5f, 15.5f, 0.0f, // top left
-15.5f, -15.5f, 0.0f, // bottom left
15.5f, -15.5f, 0.0f, // bottom right
15.5f, 15.5f, 0.0f }; // top right
int mProgram;
int mPositionHandle;
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
private final String vertexShaderCode = "attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"v_TexCoordinate = a_TexCoordinate;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"uniform sampler2D u_Texture;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
"gl_FragColor = ( texture2D(u_Texture, v_TexCoordinate));" +
"}";
public BackGround(final Context context) {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
mActivityContext = context;
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
final float[] cubeTextureCoordinateData = {
-15.5f, 15.5f,
-15.5f, -15.5f,
15.5f, -15.5f,
15.5f, 15.5f
};
mCubeTextureCoordinates =
ByteBuffer.allocateDirect(cubeTextureCoordinateData.length *
4).order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glBindAttribLocation(mProgram, 0, "a_TexCoordinate");
GLES20.glLinkProgram(mProgram);
// load background bitmap 256x256px
mTextureDataHandle = loadTexture(mActivityContext, R.drawable.mud);
}
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
mTextureUniformHandle = GLES20.glGetAttribLocation(mProgram, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
GLES20.glUniform1i(mTextureUniformHandle, 0);
mCubeTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize,
GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
The problem is that I don't know how to spread my background (256x256) over big area (not limited by screen size). currenty, texture is repeated in the screen edges only. And when im trying to move it (using SetLookAtm()) it moves ok, but leaves empty stripe behind:
Initial background image (bmp-reversed):
ab
cd
Background image at the screen:
--------
|ababab|
|cdcdcd|
|ababab|
|cdcdcd|
|ababab|
|cdcdcd|
--------
Background image after move (right ->)
--------
| abab|
| cdcd|
| abab|
| cdcd|
| abab|
| cdcd|
--------
Direction (left, right, up, down) doesnt matter. It only has effect on which side stripe appears
Either:
A) Define your background rectangle so that it extends beyond the ends of the screen (and "scroll" the background by animating its position)
--------
|ababab|ababab
|cdcdcd|cdcdcd
|ababab|ababab
|cdcdcd|cdcdcd
|ababab|ababab
|cdcdcd|cdcdcd
--------
or:
B) Define the bg rectangle filling up the screen as before, but animate the texture coordinates to make it scroll. Eg: If your texcoords form a rectangle (0.00,0.00)->(1.00,1.00), then scroll the bg left by changing texcoords to be (0.05,0.00)->(1.05,1.00). Make sure you've set glTexParameteri as follows:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

Unable to get texture to render to quad in OpenGL ES 2.0 running on Android

When I launch the project I get an ominously black quad rendered inside an expectedly cyan background. I have determined that the texture coordinates are being interpolated properly with the commented out line of code in the fragment shader. I have tried a number of different ways of loading a texture and have always got the same result. The temporary bit of code that loads the 4 pixel texture is copied verbatim out of an example from a book. However I have included this as well just in case I have made an oversight.
I have attempted to remove impertinent code. But, I'm still quite new to this and continually learning the full meaning of much of the code. Additionally, much of the code has been adapted from different sources. So, I apologize for the messiness, inconsistent variable naming, and verbosity. I do feel like the issue is in the first several lines. Thanks in advance for all insight. Even any information on how I could go about debugging this would be appreciated; I feel quite in the dark when issues come up when working on this project.
Draw Frame:
public void onDrawFrame(GL10 gl)
{
GLES20.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
update();
GLES20.glUseProgram(mProgramHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureHandle);
GLES20.glUniform1i(mTextureUniformHandle, 0);
//For some reason I think the problem is in this area
Matrix.setIdentityM(mModelMatrix, 0);
quadVerts.position(mPositionOffset);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, mStrideBytes, quadVerts);
GLES20.glEnableVertexAttribArray(mPositionHandle);
quadVerts.position(mColorOffset);
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, mStrideBytes, quadVerts);
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, quadTex);
GLES20.glEnableVertexAttribArray(2);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mOrthographicMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
//...
checkGlError("on draw frame: ");
}
Surface Changed:
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
GLES20.glViewport(0, 0, width, height);
w = width;
h = height;
final float near = 1.0f;
final float far = 10.0f;
Matrix.orthoM(mOrthographicMatrix, 0, 0, width, 0, height, near, far);
float[] pVertsData =
{
20.0f, 20.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
(float) width- 20.0f, 20.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
(float) width - 20.0f, (float) height - 20.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
20.0f, (float) height - 20.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
quadVerts = ByteBuffer.allocateDirect(pVertsData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
quadVerts.put(pVertsData).position(0);
float texture[] =
{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
quadTex = ByteBuffer.allocateDirect(texture.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
quadTex.put(texture).position(0);
checkGlError("surface changed: ");
}
Surface Created:
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
mParticleSystem = new ParticleSystem();
//GLES20.glEnable(GLES20.GL_TEXTURE_2D);
if (mTextureHandle != 1)
mTextureHandle = loadGLTexture(activeContext, resourceID);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 1.5f;
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "attribute vec4 a_Color; \n"
+ "attribute vec2 a_TexCoordinate; \n"
+ "//varying vec3 v_Position; \n"
+ "varying vec4 v_Color; \n"
+ "varying vec2 v_TexCoordinate; \n"
+ "void main() \n"
+ "{ \n"
+ " v_TexCoordinate = a_TexCoordinate; \n"
+ " v_Color = a_Color; \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ "} \n";
final String fragmentShader =
"precision mediump float; \n"
+ "uniform sampler2D u_Texture; \n"
+ "varying vec4 v_Color; \n"
+ "varying vec2 v_TexCoordinate; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor;"
+ " baseColor = texture2D(u_Texture, v_TexCoordinate); \n"
+ " "
+ " gl_FragColor = baseColor; \n"
+ " \n"
+ " //gl_FragColor = vec4(v_TexCoordinate.x, v_TexCoordinate.y, 0.0, 1.0); \n"
+ " //gl_FragColor = v_Color; \n"
+ "} \n";
//... Compile Shaders
int programHandle = GLES20.glCreateProgram();
if (programHandle != 0)
{
GLES20.glAttachShader(programHandle, vertexShaderHandle);
GLES20.glAttachShader(programHandle, fragmentShaderHandle);
GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
GLES20.glBindAttribLocation(programHandle, 1, "a_Color");
GLES20.glBindAttribLocation(programHandle, 2, "a_TexCoordinate");
GLES20.glLinkProgram(programHandle);
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
}
}
if (programHandle == 0)
{
throw new RuntimeException("Error creating program.");
}
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
mColorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");
mTextureUniformHandle = GLES20.glGetUniformLocation(programHandle, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(programHandle, "a_TexCoordinate");
//GLES20.glUseProgram(programHandle);
mProgramHandle = programHandle;
checkGlError("surface created: ");
}
Load Texture:
private int loadGLTexture(Context context, final int resourceId)
{
final int[] textureHandle = new int[1];
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
GLES20.glGenTextures(1, textureHandle, 0);
byte[] pixels =
{
(byte) 0xff, 0, 0,
0, (byte) 0xff, 0,
0, 0, (byte) 0xff,
(byte) 0xff, (byte) 0xff, 0
};
ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(4*3);
pixelBuffer.put(pixels).position(0);
GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textureHandle[0] );
GLES20.glTexImage2D ( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, 2, 2, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, pixelBuffer );
GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST );
GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
checkGlError("create texture: ");
return textureHandle[0];
}
Code updated as suggested below.
Finally, located the problem. I removed a lot of commented out lines in the posted code for simplicity's sake. One of which was the line in the fragment shader directly before "gl_FragColor = baseColor;". However this line did not have '\n'... So in effect I had commented out the line that was supposed to actually put the texture on the quad. So the code above will actually run properly while the code that was in my project would not.
Couple thoughts. I don't know if your problem is in here, but here goes:
You're not doing any error checking with glGetError (you should do this). It will help you find so many problems.
GLES20.glEnable(GLES20.GL_TEXTURE_2D); is not a legal call in GLES2.0. Enabling GL_TEXTURE_2D only effects the deprecated fixed function pipeline. This is likely generating an error, but shouldn't cause your problem.
Can you try adding error checking, and report back if there are any problems? I scanned your code a bit but it looks pretty correct so far.

Categories

Resources