Reputation: 1
I need to render an image of size 1000x800 on an android device. If i create width and height of 2x2 image is rendered properly. If anything above this size that is 2x2 my image is not displayed properly, texture appears to be grabage. I am using Opengl ES 2.0. I tried setting orthoM matrix in various ways but above 2x2 width and height everything appears bad. How do i map image pixel to device pixel. I created meshgrid for image which starts from (0,0) and goes uptil width and height. That means to say my coordinate doesnt start at the centere where as it starts at top left corner.
I have created vertex buffer, short index( order list to draw triangles) and texture coordinates like this.
public MeshGrid(int width, int height) {
vertices = new float[(width) * (height) * 2];
indices = new short[(width-1) * (height-1) * 6];
textu = new float[(width-1) * (height-1) * 8];
float xOffset = width / -2;
float yOffset = height / -2;
int currentVertex = 0;
int currentIndex = 0;
int currentTexIndex = 0;
short w = (short) (width );
for (int y = 0; y < height ; y++) {
for (int x = 0; x < width ; x++) {
vertices[currentVertex] = x;
vertices[currentVertex + 1] = y ;
currentVertex += 2;
int n = y * (width ) + x;
if (y < width-1 && x < height-1) {
// Face one
indices[currentIndex] = (short) n;
indices[currentIndex + 1] = (short) (n + 1);
indices[currentIndex + 2] = (short) (n + w);
// Face two
indices[currentIndex + 3] = (short) (n + 1);
indices[currentIndex + 4] = (short)(n + 1 + w);
indices[currentIndex + 5] = (short) (n + 1 + w - 1);
currentIndex += 6;
textu[currentTexIndex] = x;
textu[currentTexIndex+1] = y+1;
textu[currentTexIndex+2] = x+1;
textu[currentTexIndex+3] = y+1;
textu[currentTexIndex+4] = x;
textu[currentTexIndex+5] = y;
textu[currentTexIndex+6] = x+1;
textu[currentTexIndex+7] = y;
currentTexIndex+= 8;
}
}
}
}
I have set them like this
ByteBuffer bb = ByteBuffer.allocateDirect( // (# of coordinate values * 4 bytes per float) imgVertices.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(imgVertices); vertexBuffer.position(0);
ByteBuffer vbb = ByteBuffer.allocateDirect(imgIndices.length * 2);
vbb.order(ByteOrder.nativeOrder());
indicesBuffer = vbb.asShortBuffer();
indicesBuffer.put(imgIndices);
indicesBuffer.position(0);
mNumOfIndices = imgIndices.length;
ByteBuffer byteBuf = ByteBuffer
.allocateDirect(imgTexture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(imgTexture);
mTextureSize = imgTexture.length;
textureBuffer.position(0);
This is my verterx shader code
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec2 a_TexCoordinate;" +
"attribute vec2 a_Position;" +
"varying vec2 v_TexCoordinate;" +
"varying vec3 v_Position;" +
"void main() {" +
" v_TexCoordinate = a_TexCoordinate;" +
"gl_Position = uMVPMatrix*vec4(a_Position.x,a_Position.y,1.0,1.0);"+
"}";
This is my fragment shader code
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);" +
"}";
This is How i set my projection and view matrix
Matrix.setIdentityM(mProjectionMatrix, 0);
float ratio = (float)mwidth/mheight;
Matrix.orthoM(mProjectionMatrix,0,0f,ratio,0f,1,1,-1);
Matrix.setIdentityM(mViewMatrix, 0);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
This is my draw function
void drawImg() {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
GLES20.glVertexAttrib2fv(mPositionHandle, vertexBuffer);
// 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(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
checkGlError("glUniformMatrix4fv");
mTxetureaformHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
// Pass in the texture coordinate information
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// Bind the texture to this unit.
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
textureBuffer.position(0);
GLES20.glVertexAttribPointer(mTxetureaformHandle, 2, GLES20.GL_FLOAT, false,
0, textureBuffer);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTxetureHandle);
GLES20.glEnableVertexAttribArray(mTxetureaformHandle);
GLES20.glUniform1i(mTextureUniformHandle, 0);
// Point out the where the color buffer is.
GLES20.glDrawElements(GL10.GL_TRIANGLES, mNumOfIndices,
GL10.GL_UNSIGNED_SHORT, indicesBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
Upvotes: 0
Views: 61
Reputation: 86
If you just want to draw an image you don't need to draw a whole grid of vertices on the screen (but see below if you wanted to draw sub-parts of the image). All you need to do is draw one rectangle the size of the screen. Use your screen width for the "right" variable in orthoM, and height for the "top" variable:
Matrix.orthoM(someMatrix, 0, 0f, width, 0.0f, height, 0, 50);
Then your vertices can be like this:
vertices = new float[] {
0.0f, 0.0f,
0.0f, height,
width, height,
width, 0.0f
};
and your texture coordinates:
uvs = new float[] {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
Note that the y-axis is inverted in Android as compared to the default image editors, but you'll notice this quickly when your image is displayed upside down.
Now I'm not sure why you were making such a big grid of vertices to begin with. Possibly you wanted only certain parts of the image in certain corners of the screen. In that case you have to adjust the vertices and/or the texture coordinates. For example if you want 1/8th of the screen filled divide the coordinates of the vertices by 8. If you only want a quarter of the texture replace all 1.0f with 0.5f, you'll get the top left of your image (depending if your y-axis was inverted).
Upvotes: 0