android openGL Es 2 showing no image - android

I am new to Android's OpenGL ES. I have spent 3 days in texture mapping but did not get any solution to my problem. Now I have written some code but it's only showing the background color but not the image that I want to show on the surface. Here is the myRenderer class constructor
public myRenderer()
{
imageBitmap=BitmapFactory.decodeResource(MainActivity.context.getResources(),R.drawable.image);
float texture[]={
0.0f, 0.0f, //bottom-left
0.1f, 0.0f, // bottom-right
0.0f, 0.1f, // top-left
0.1f, 0.1f // top-right
};
float vertex[]={
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, //3 Vertex Coords, 3 RGB Vals
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, //3 Vertex Coords, 3 RGB Vals
0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, //3 Vertex Coords, 3 RGB Vals
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, //3 Vertex Coords, 3 RGB Vals
1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, //3 Vertex Coords, 3 RGB Vals
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, //3 Vertex Coords, 3 RGB Vals
};
float triagnle2[]={
-0.75f,0.5f,0.0f,
0.0f,1.0f,0.0f,1.0f,
0.75f,0.5f,0.0f,
1.0f,1.0f,0.0f,1.0f,
0.0f,0.0f,0.0f,
1.0f,1.0f,1.0f,1.0f
};
byte[] indices={
0,1,2, 3,4,5//Front Face
};
vertexBuffer=ByteBuffer.allocateDirect(vertex.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertex).position(0);
textureBuffer=ByteBuffer.allocateDirect(texture.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
textureBuffer.put(texture).position(0);
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
}
Here is what's in SurfaceCreated:
GLES20.glClearColor(1.7f,1.5f,0.5f,0.5f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
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);
//imageBitmap.getPixels(pixels,0,imageBitmap.getWidth(),0,0,imageBitmap.getWidth(),imageBitmap.getHeight());
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, imageBitmap, 0);
imageBitmap.recycle();
GLES20.glDepthFunc(GLES20.GL_LESS);
Matrix.setIdentityM(mModelMatrix,0);
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 2.5f;
// We are looking toward the distance
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = 1f;
// Set our up vector. This is where our head would be pointing were we holding the camera.
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" // A constant representing the combined model/view/projection matrix.
+ "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.
+"attribute vec2 TextureCoord;"
+"varying vec2 TextureCoordOut;"
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
// + " v_Color = a_Color; \n" // Pass the color through to the fragment shader.
+"TextureCoordOut = TextureCoord;" // 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
+"varying mediump vec2 TextureCoordOut;"
+"uniform sampler2D Sampler;// precision in the fragment shader."
//+ "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = vec4(texture2D(Sampler, TextureCoordOut).xyz, 0.5); \n" // Pass the color directly through the pipeline.
+ "} \n";
int vertexShederHandle=GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if(vertexShederHandle!=0)
{
GLES20.glShaderSource(vertexShederHandle, vertexShader);
GLES20.glCompileShader(vertexShederHandle);
int[] compileStatus=new int[1];
GLES20.glGetShaderiv(vertexShederHandle,GLES20.GL_COMPILE_STATUS,compileStatus,0);
if(compileStatus[0]==0)
{
GLES20.glDeleteShader(vertexShederHandle);
vertexShederHandle=0;
}
}
else
{
throw new RuntimeException("Error creating Sheder");
}
/////////////
int fragmentShederHandle=GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if(fragmentShederHandle!=0)
{
GLES20.glShaderSource(fragmentShederHandle,fragmentShader);
GLES20.glCompileShader(fragmentShederHandle);
int[] compileStatus=new int[1];
GLES20.glGetShaderiv(fragmentShederHandle,GLES20.GL_COMPILE_STATUS,compileStatus,0);
if(compileStatus[0]==0)
{
GLES20.glDeleteShader(fragmentShederHandle);
fragmentShederHandle=0;
}
}
else
{
throw new RuntimeException("Error creating Sheder");
}
int progameHandle=GLES20.glCreateProgram();
if(progameHandle!=0)
{
GLES20.glAttachShader(progameHandle, vertexShederHandle);
GLES20.glAttachShader(progameHandle, fragmentShederHandle);
GLES20.glBindAttribLocation(progameHandle, 0, "a_Position");
GLES20.glBindAttribLocation(progameHandle, 1, "a_Color");
GLES20.glLinkProgram(progameHandle);
int[] linkStatus=new int[1];
GLES20.glGetProgramiv(progameHandle, GLES20.GL_LINK_STATUS,linkStatus,0);
if(linkStatus[0]==0)
{
GLES20.glDeleteProgram(progameHandle);
progameHandle=0;
}
}
else
{
throw new RuntimeException("Error creating programe");
}
mMVPMatrixHandle=GLES20.glGetUniformLocation(progameHandle, "u_MVPMatrix");
mPositionHandle=GLES20.glGetAttribLocation(progameHandle, "a_Position");
mColorHandle=GLES20.glGetAttribLocation(progameHandle, "a_Color");
GLES20.glUseProgram(progameHandle);
Here is OnSurfaceChanged:
GLES20.glViewport(0, 0, width, height);
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 0.4f;
final float far = 10.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
And here is onDrawFrame:
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glEnable(GLES20.GL_VERTEX_ATTRIB_ARRAY_ENABLED);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0+textures[0]);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP,6,GLES20.GL_UNSIGNED_BYTE,indexBuffer);
forgive me if doing some stupidity..
please tell me what to do.
thank you.

I'm not sure what you're intending this call to do: GLES20.glEnable(GLES20.GL_VERTEX_ATTRIB_ARRAY_ENABLED), but that's not a legal target to glEnable and is almost certainly generating a gl error.
Put some glGetError throughout your code and try to find the lines that might be causing you errors, and if you have no errors, please update the question with that fact so we know what else to look for.

Related

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.

Can't Draw Squares in OpenGL ES 2.0 for Android, but Can Draw Triangles

So i took code from http://www.learnopengles.com/android-lesson-one-getting-started/ and have been trying to draw a square (while still keeping everything else in the background). For whatever reason, it shows up as a triangle. My code will be provided below. I knew to change GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 4), but I can't find out what else I'm missing.
Furthermore, is there a better way to find out how to use functions within the class GLES20? http://developer.android.com/reference/android/opengl/GLES20.html does a good job providing parameters, but doesn't explain what each parameter does.
I would imagine my error is at the bottom of my code, probably in the function drawSquare, but the entire file will be pasted here in case I'm mistaken.
public class LessonOneRenderer implements GLSurfaceView.Renderer
{/**
* Store the model matrix. This matrix is used to move models from object space (where each model can be thought
* of being located at the center of the universe) to world space.
*/
private float[] mModelMatrix = new float[16];
/**
* Store the view matrix. This can be thought of as our camera. This matrix transforms world space to eye space;
* it positions things relative to our eye.
*/
private float[] mViewMatrix = new float[16];
/** Store the projection matrix. This is used to project the scene onto a 2D viewport. */
private float[] mProjectionMatrix = new float[16];
/** Allocate storage for the final combined matrix. This will be passed into the shader program. */
private float[] mMVPMatrix = new float[16];
/** Store our model data in a float buffer. */
private final FloatBuffer mTriangle1Vertices;
private final FloatBuffer mTriangle2Vertices;
private final FloatBuffer mTriangle3Vertices;
private final FloatBuffer mSquare1Vertices;
/** This will be used to pass in the transformation matrix. */
private int mMVPMatrixHandle;
/** This will be used to pass in model position information. */
private int mPositionHandle;
/** This will be used to pass in model color information. */
private int mColorHandle;
/** How many bytes per float. */
private final int mBytesPerFloat = 4;
/** How many elements per vertex. */
private final int mStrideBytes = 7 * mBytesPerFloat;
/** Offset of the position data. */
private final int mPositionOffset = 0;
/** Size of the position data in elements. */
private final int mPositionDataSize = 3;
/** Offset of the color data. */
private final int mColorOffset = 3;
/** Size of the color data in elements. */
private final int mColorDataSize = 4;
/**
* Initialize the model data.
*/
public LessonOneRenderer()
{
// Define points for equilateral triangles.
// This triangle is red, green, and blue.
final float[] triangle1VerticesData = {
// X, Y, Z,
// R, G, B, A
-0.5f, -0.25f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.25f, 0.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.559016994f, 0.0f,
0.0f, 1.0f, 0.0f, 1.0f};
// This triangle is yellow, cyan, and magenta.
final float[] triangle2VerticesData = {
// X, Y, Z,
// R, G, B, A
-0.5f, -0.25f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.25f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 0.559016994f, 0.0f,
1.0f, 0.0f, 1.0f, 1.0f};
// This triangle is white, gray, and black.
final float[] triangle3VerticesData = {
// X, Y, Z,
// R, G, B, A
-0.5f, -0.25f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.25f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f,
0.0f, 0.559016994f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};
final float[] square1VerticesData = {
//topleft
-0.25f, 0.25f, -.5f,
1.0f, 0.0f, 0.0f, 1.0f,
//top right
0.25f,0.25f, -.5f,
0.0f, 1.0f, 0.0f, 1.0f,
//bottom left
-0.25f, -0.25f, -.5f,
1.0f, 0.0f, 0.0f, 1.0f,
//right
0.25f, -0.25f, -.5f,
1.0f, 0.0f, 0.0f, 1.0f};
// Initialize the buffers.
mTriangle1Vertices = ByteBuffer.allocateDirect(triangle1VerticesData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangle2Vertices = ByteBuffer.allocateDirect(triangle2VerticesData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangle3Vertices = ByteBuffer.allocateDirect(triangle3VerticesData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mSquare1Vertices = ByteBuffer.allocateDirect(square1VerticesData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangle1Vertices.put(triangle1VerticesData).position(0);
mTriangle2Vertices.put(triangle2VerticesData).position(0);
mTriangle3Vertices.put(triangle3VerticesData).position(0);
mSquare1Vertices.put(square1VerticesData).position(0);
}
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
// Set the background clear color to gray.
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
// Position the eye behind the origin.
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 1.5f;
// We are looking toward the distance
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;
// Set our up vector. This is where our head would be pointing were we holding the camera.
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
// Set the view matrix. This matrix can be said to represent the camera position.
// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
// view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "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.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
+ " v_Color = a_Color; \n" // Pass the color 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"; // normalized screen coordinates.
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.
+ "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline.
+ "} \n";
// Load in the vertex shader.
int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(vertexShaderHandle, vertexShader);
// Compile the shader.
GLES20.glCompileShader(vertexShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
}
}
if (vertexShaderHandle == 0)
{
throw new RuntimeException("Error creating vertex shader.");
}
// Load in the fragment shader shader.
int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
// Compile the shader.
GLES20.glCompileShader(fragmentShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(fragmentShaderHandle);
fragmentShaderHandle = 0;
}
}
if (fragmentShaderHandle == 0)
{
throw new RuntimeException("Error creating fragment shader.");
}
// Create a program object and store the handle to it.
int programHandle = GLES20.glCreateProgram();
if (programHandle != 0)
{
// Bind the vertex shader to the program.
GLES20.glAttachShader(programHandle, vertexShaderHandle);
// Bind the fragment shader to the program.
GLES20.glAttachShader(programHandle, fragmentShaderHandle);
// Bind attributes
GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
GLES20.glBindAttribLocation(programHandle, 1, "a_Color");
// Link the two shaders together into a program.
GLES20.glLinkProgram(programHandle);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
// If the link failed, delete the program.
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
}
}
if (programHandle == 0)
{
throw new RuntimeException("Error creating program.");
}
// Set program handles. These will later be used to pass in values to the program.
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
mColorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");
// Tell OpenGL to use this program when rendering.
GLES20.glUseProgram(programHandle);
}
#Override
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
// Set the OpenGL viewport to the same size as the surface.
GLES20.glViewport(0, 0, width, height);
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
#Override
public void onDrawFrame(GL10 glUnused)
{
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
// Do a complete rotation every 10 seconds.
long time = SystemClock.uptimeMillis() % 10000L;
float angleInDegrees = (360.0f / 10000.0f) * ((int) time);
// Draw the triangle facing straight on.
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);
drawTriangle(mTriangle1Vertices);
// Draw one translated a bit down and rotated to be flat on the ground.
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0.0f, -1.0f, 0.0f);
Matrix.rotateM(mModelMatrix, 0, 90.0f, 1.0f, 0.0f, 0.0f);
Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);
drawTriangle(mTriangle2Vertices);
// Draw one translated a bit to the right and rotated to be facing to the left.
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 1.0f, 0.0f, 0.0f);
Matrix.rotateM(mModelMatrix, 0, 90.0f, 0.0f, 1.0f, 0.0f);
Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);
drawTriangle(mTriangle3Vertices);
// Draw square facing strait on
float smallerAngle = -angleInDegrees;
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0, 0, 0.0f);
Matrix.rotateM(mModelMatrix, 0, smallerAngle, 0.0f, 0.0f, 1.0f);
drawSquare(mSquare1Vertices);
}
/**
* Draws a triangle from the given vertex data.
*
* #param aTriangleBuffer The buffer containing the vertex data.
*/
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);
// Pass in the color information
aTriangleBuffer.position(mColorOffset);
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
// 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, 3);
}
private void drawSquare(final FloatBuffer aSquareBuffer) {
// Pass in the position information
aSquareBuffer.position(mPositionOffset);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, aSquareBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Pass in the color information
aSquareBuffer.position(mColorOffset);
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, aSquareBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
// 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, 4);
}
}
I'm assuming that you are very new to OpenGL ES 2.0 programming. So, before you start playing around with 3.D-transformation matrices (such as, for modeling, viewing, or projection) please try this basic example first (to render a rectangle) -
public class GLES20Renderer implements Renderer {
private int _rectangleProgram;
private int _rectangleAPositionLocation;
private FloatBuffer _rectangleVFB;
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 1);
initShapes();
int _rectangleVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, _rectangleVertexShaderCode);
int _rectangleFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, _rectangleFragmentShaderCode);
_rectangleProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(_rectangleProgram, _rectangleVertexShader);
GLES20.glAttachShader(_rectangleProgram, _rectangleFragmentShader);
GLES20.glLinkProgram(_rectangleProgram);
_rectangleAPositionLocation = GLES20.glGetAttribLocation(_rectangleProgram, "aPosition");
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
public void onDrawFrame(GL10 gl) {
gl.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(_rectangleProgram);
GLES20.glVertexAttribPointer(_rectangleAPositionLocation, 3, GLES20.GL_FLOAT, false, 12, _rectangleVFB);
GLES20.glEnableVertexAttribArray(_rectangleAPositionLocation);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
private void initShapes() {
float rectangleVFA[] = {
0, 0, 0,
0, 0.5f, 0,
0.75f, 0.5f, 0,
0.75f, 0.5f, 0,
0.75f, 0, 0,
0, 0, 0,
};
ByteBuffer rectangleVBB = ByteBuffer.allocateDirect(rectangleVFA.length * 4);
rectangleVBB.order(ByteOrder.nativeOrder());
_rectangleVFB = rectangleVBB.asFloatBuffer();
_rectangleVFB.put(rectangleVFA);
_rectangleVFB.position(0);
}
private final String _rectangleVertexShaderCode =
"attribute vec4 aPosition; \n"
+ "void main() { \n"
+ " gl_Position = aPosition; \n"
+ "} \n";
private final String _rectangleFragmentShaderCode =
"void main() { \n"
+ " gl_FragColor = vec4(1,1,1,1); \n"
+ "} \n";
private int loadShader(int type, String source) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
return shader;
}
}
More of these at -
http://www.apress.com/9781430250531
Define your square as two triangles. I do it this way (I give you an example without color data, only vertices):
final float[] squareCoords = {
//first triangle
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
//second triangle
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f
};
And then, in drawSquare() use
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
It will draw two triangles with your square coords.

What is the easiest way to draw line using OpenGL-ES (android)

If I have custom renderer in opengl-es prepared:
public void onDrawFrame(GL10 gl)
{
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// here i want to draw line from [0, 0, 0] to [1, 0, 0]
}
What is the easiest and shortest way to draw line?
In ordinary OpenGL it is:
glBegin(GL_LINES);
glVertex3f(0, 0, 0);
glVertex3f(1, 0, 0);
glEnd();
But how can i get the same effect with OpenGL ES?
I am new to new to OpenGL ES 2.0 but I created a line class.
public class Line {
private FloatBuffer VertexBuffer;
private final String VertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String FragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
protected int GlProgram;
protected int PositionHandle;
protected int ColorHandle;
protected int MVPMatrixHandle;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float LineCoords[] = {
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
private final int VertexCount = LineCoords.length / COORDS_PER_VERTEX;
private final int VertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
public Line() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
LineCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
VertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
VertexBuffer.put(LineCoords);
// set the buffer to read the first coordinate
VertexBuffer.position(0);
int vertexShader = ArRenderer.loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
int fragmentShader = ArRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);
GlProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(GlProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(GlProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(GlProgram); // creates OpenGL ES program executables
}
public void SetVerts(float v0, float v1, float v2, float v3, float v4, float v5) {
LineCoords[0] = v0;
LineCoords[1] = v1;
LineCoords[2] = v2;
LineCoords[3] = v3;
LineCoords[4] = v4;
LineCoords[5] = v5;
VertexBuffer.put(LineCoords);
// set the buffer to read the first coordinate
VertexBuffer.position(0);
}
public void SetColor(float red, float green, float blue, float alpha) {
color[0] = red;
color[1] = green;
color[2] = blue;
color[3] = alpha;
}
public void draw(float[] mvpMatrix) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(GlProgram);
// get handle to vertex shader's vPosition member
PositionHandle = GLES20.glGetAttribLocation(GlProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(PositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
VertexStride, VertexBuffer);
// get handle to fragment shader's vColor member
ColorHandle = GLES20.glGetUniformLocation(GlProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(ColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
MVPMatrixHandle = GLES20.glGetUniformLocation(GlProgram, "uMVPMatrix");
ArRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
ArRenderer.checkGlError("glUniformMatrix4fv");
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_LINES, 0, VertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(PositionHandle);
}
}
And then in my Render class I create my line objects and to a container so the get draw in the by iterating over the items and calling the Line.draw method in onDrawFrame.
Here are some lines I create to make a horizon:
Line eastHorz = new Line();
eastHorz.SetVerts(10f, 10f, 0f, 10f, -10f, 0f);
eastHorz.SetColor(.8f, .8f, 0f, 1.0f);
Line northHorz = new Line();
northHorz.SetVerts(-10f, 10f, 0f, 10f, 10f, 0f);
northHorz.SetColor(0.8f, 0.8f, 0f, 1.0f);
Line westHorz = new Line();
westHorz.SetVerts(-10f, -10f, 0f, -10f, 10f, 0f);
westHorz.SetColor(0.8f, 0.8f, 0f, 1.0f);
Line southHorz = new Line();
southHorz.SetVerts(-10f, -10f, 0f, 10f, -10f, 0f);
southHorz.SetColor(0.8f, 0.8f, 0f, 1.0f);
Lines.add(eastHorz);
Lines.add(northHorz);
Lines.add(westHorz);
Lines.add(southHorz);
ArRenderer is my render class which holds the Lines, camera position etc and implements GLSurfaceView.Renderer. The loadShader method is:
public static int loadShader(int type, String shaderCode) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
Thanks Rodney Lambert for the Line class you´ve provided. However it also would be nice to provide a simpler call in onDrawFrame, something like:
Line vertLine = new Line();
vertLine.SetVerts(-0.5f, 0.5f, 0f, -0.5f, -0.5f, 0f);
vertLine.SetColor(.8f, .8f, 0f, 1.0f);
vertLine.draw(mMVPMatrix);
vertLine.SetVerts(-0.5f, 0.5f, 0f, -0.5f, -0.5f, 0f);
creates definitely a line visible inside the viewport

OGL ES 2.0 Orthogonal Matrix result position unexpected

I'm having some trouble figuring out, why my triangle is not rendered at the expected position.
I want to draw this triangle:
private float vVertices[] = { 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f};
First I create a Projection Matrix as described here
float aspect_ratio = 800.0f/480.0f;
ortho_matrix(-aspect_ratio, aspect_ratio, -1.0f, 1.0f, -1.0f, 1.0f, PROJECTION_MATRIX);
Then I create a View Matrix and multiply those two:
Matrix.setLookAtM(VIEW_MATRIX, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, PROJECTION_MATRIX, 0, VIEW_MATRIX, 0);
Now I send the mvpMatrix to my Shader,
String vertexShader = "attribute vec4 vPosition; \n" +
"uniform mat4 orthoMatrix;" +
"void main()\n" +
"{\n" +
" gl_Position = vPosition * orthoMatrix;" +
"}";
where the vertices are translated using this matrix.
However, this is not the result I was expecting.
The following image is the result of the above code:
I expected the triangle to have its origin in 0, 0, 0 - so in the center of the screen like this:
From the above code, can anyone tell me what I did wrong, or what I did miss?
edit
Ok, it seems the koordinates are somehow mirrored...
so it looks like this
1 ----+---- -1
When I inverse the aspect_ratio parameters in the ortho_matrix call it looks right. But why is this nessecary?
You're doing the vertex shader multiplication backwards.
It should be :
gl_Position = orthoMatrix * vPosition;

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