I tried to render some 2D object and I am able to do that but now I tried to render some images in opengl but it not showing anything. Here is my image rendering code .
package com.example.androidinternalmaps;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
public class ImageObject
{
private final Context mActivityContext;
private final FloatBuffer mCubeTextureCoordinates;
private int mTextureUniformHandle;
private int mTextureCoordinateHandle;
private final int mTextureCoordinateDataSize = 2;
private int mTextureDataHandle;
private final String VerShader =
"uniform mat4 u_Matrix;"+
"attribute vec4 a_Position;"+
"attribute vec2 a_TextureCoordinates;"+
"varying vec2 v_TextureCoordinates;"+
"void main()"+
"{"+
"v_TextureCoordinates = a_TextureCoordinates;"+
"gl_Position = u_Matrix * a_Position;"+
"}";
private final String FragShader =
"precision mediump float;"+
"uniform sampler2D u_TextureUnit;"+
"varying vec2 v_TextureCoordinates;"+
"void main()"+
"{"+
"gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);"+
"}";
private final int shaderProgram;
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
static final int COORDS_PER_VERTEX = 2;
static float spriteCoords[] = { -0.5f, 0.5f, // top left
-0.5f, -0.5f, // bottom left
0.5f, -0.5f, // bottom right
0.5f, 0.5f }; //top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; //Order to draw vertices
private final int vertexStride = COORDS_PER_VERTEX * 4; //Bytes per vertex
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
public ImageObject(final Context activityContext)
{
mActivityContext = activityContext;
ByteBuffer bb = ByteBuffer.allocateDirect(spriteCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(spriteCoords);
vertexBuffer.position(0);
final float[] cubeTextureCoordinateData =
{
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f
};
mCubeTextureCoordinates = ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);
//Initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(spriteCoords.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, VerShader);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, FragShader);
shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertexShader);
GLES20.glAttachShader(shaderProgram, fragmentShader);
//Texture Code
GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");
GLES20.glLinkProgram(shaderProgram);
//Load the texture
mTextureDataHandle = loadTexture(mActivityContext, R.drawable.air_hockey_surface);
}
public void Draw(float[] mvpMatrix)
{
//Add program to OpenGL ES Environment
GLES20.glUseProgram(shaderProgram);
//Get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
//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
mColorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor");
//Set the Color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//Set Texture Handles and bind Texture
mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "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);
//Pass in the texture coordinate information
mCubeTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
//Get Handle to Shape's Transformation Matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
//Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
//Disable Vertex Array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
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];
}
}
It is not showing anything. Just blank screen. I Don't know what I am doing wrong. Need Help. Thank you .
My renderer class
package com.example.androidinternalmaps;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
public class MyGLRenderer implements GLSurfaceView.Renderer {
private FloorPolygon floorPolygon;
private ImageObject imageObject;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private float originX = 0.0f, originY = 0.0f;
private float translationDx=0.0f,translationDy=0.0f;
private float originScaleX = 2.5f, originScaleY = 2.5f;
private float scaleDx = 1.0f, scaleDy = 1.0f;
private float surfaceViewWidth, surfaceViewHeight;
private Context mContext;
public MyGLRenderer(Context context)
{
mContext = context;
}
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
floorPolygon = new FloorPolygon();
imageObject = new ImageObject(mContext);
}
public void onDrawFrame(GL10 unused)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.translateM(mMVPMatrix, 0, originX+translationDx, originY+translationDy, 0.0f);
Matrix.scaleM(mMVPMatrix, 0, scaleDx*originScaleX, scaleDy*originScaleY, 0.0f);
imageObject.Draw(mMVPMatrix);
}
public void onSurfaceChanged(GL10 unused, int width, int height)
{
surfaceViewHeight = height;
surfaceViewWidth = width;
GLES20.glViewport(0, 0, width, height);
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public static int loadShader(int type, String shaderCode)
{
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void setTranslationPoints(float translationDx, float translationDy)
{
this.translationDx = ((translationDx/surfaceViewWidth)*2);
this.translationDy = -((translationDy/surfaceViewHeight)*2);
}
public void setScalePoints(float scaleDx, float scaleDy)
{
this.scaleDx = scaleDx;
this.scaleDy = scaleDy;
}
}
One issue I think is this:
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Your look vector is (0,0,0) which doesn't describe a direction. Your eye position is (0,0,5), indicating a position towards you along the z-axis from the origin. So your look vector needs to be away from you back towards the origin. Therefore try changing the look vector to (0,0,-1):
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, -1f, 0f, 1.0f, 0.0f);
EDIT:
For starters, move this to onSurfaceChanged since you don't need to call it on every frame, just when the surface gets constructed:
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, -1f, 0f, 1.0f, 0.0f);
Now for the ImageObject class. In your vertex shader, change 'a_TextureCoordinates' to 'a_TexCoordinate' so that the name matches what you use in your constructor code.
In the constructor, make this change:
//GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");
GLES20.glBindAttribLocation(shaderProgram, 0, "a_Position");
GLES20.glBindAttribLocation(shaderProgram, 1, "a_TexCoordinate");
Before you were binding "a_TexCoordinate" to position 0 but it should be position 1 since it's the 2nd attribute in the shader. The first attribute in your shader is "a_Position" so should be bound to position 0.
In Draw, make these changes:
//mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "a_Position");
//mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture");
mTextureUniformHandle = GLES20.glGetUniformLocation(shaderProgram, "u_TextureUnit");
//mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "u_Matrix");
That's because the names don't match up correctly with the names in the shaders. For the texture handler, this is a Uniform, not an Attribute hence you need to use glGetUniformLocation.
That should be it I think. I've run your code and I'm getting a texture drawn across the screen.