why it is not a cube? - android

I am working on a simple project which dras a cube and rotates it in OpenGLES 2.0 android 4.1. but the drawed shape wasnt cube. and it is rotating a axis that i wasnt supposed to. i suppose it rotates X,Y axis in camera space. so thanks for your advice.
public float mAngleX;
public float mAngleY;
private Quadrat quad;
private final float[] MVPMatrix = new float[16];
private final float[] projectionMatrix = new float[16];
private final float[] mVMatrix = new float[16];
private final float[] rotationMatrix = new float[16];
public MyRenderer(){
mAngleX = 0;
mAngleY = 0;
}
// #Override
public void onSurfaceCreated(GL10 unused, EGLConfig config){
// Set the background frame color
GLES20.glClearColor(0.5f, 0.2f, 0.1f, 1.0f);
Matrix.setLookAtM(mVMatrix, 0, 0.0f, 0.0f, -5.0f, 0f, 0f, 1f, 0f, 1.0f, 0.0f);
quad = new Quadrat();
}
// #Override
public void onSurfaceChanged(GL10 unused, int width, int height){
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.perspectiveM(projectionMatrix, 0, 45.0f, ratio, 1, 9);
}
//#Override
public void onDrawFrame(GL10 unused) {
// Draw background color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setRotateM(rotationMatrix, 0, mAngleX, 0.0f, 1.0f, 0.0f);
Matrix.multiplyMM(MVPMatrix, 0, rotationMatrix, 0, MVPMatrix, 0);
Matrix.setRotateM(rotationMatrix, 0, mAngleY, 1.0f, 0.0f, 0.0f);
Matrix.multiplyMM(MVPMatrix, 0, rotationMatrix, 0, MVPMatrix, 0);
Matrix.multiplyMM(MVPMatrix, 0, projectionMatrix, 0, mVMatrix, 0);
quad.draw(MVPMatrix, mVMatrix);
}
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
and the quadrat class is below.
class Quadrat {
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uMVMatrix;\n" +
"uniform vec3 uLightPos;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aColor;\n" +
"attribute vec4 aNormal;\n" +
"varying vec4 vColor;\n" +
"void main() {\n" +
"gl_Position = uMVPMatrix * aPosition;\n" +
"}\n";
private final String fragmentShaderCode =
"precision mediump float;\n" +
"varying vec4 vColor;\n" +
"void main() {\n" +
"gl_FragColor = vec4(1.0, 0.9, 0.4, 1.0);\n" +
"}\n";
private final FloatBuffer vertexBuffer;
private final int mProgram;
private int mPositionHandle;
private int muMVPMatrixHandle;
private int muLightPosHandle;
private int muMVMatrixHandle;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float quadrateCoords[] = { // in counterclockwise order:
// front
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
// back
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// left
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
// right
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
// up
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// bottom
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f
};
private final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex
public Quadrat() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(quadrateCoords.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(quadrateCoords);
vertexBuffer.position(0);
// prepare shaders and OpenGL program
int vertexShader = MyRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
}
public void draw(float[] mvpMatrix, float[] mVMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's aPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
// Enable a handle to the triangle vertices
// Prepare the triangle coordinate data
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
vertexStride, vertexBuffer2);
vertexStride, vertexBuffer3);
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpMatrix, 0);
muMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVMatrix");
GLES20.glUniformMatrix4fv(muMVMatrixHandle, 1, false, mVMatrix, 0);
muLightPosHandle = GLES20.glGetUniformLocation(mProgram, "uLightPos");
GLES20.glUniform3f(muLightPosHandle, 10.0f, 10.0f, 15.0f);
// Front
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// Back
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 4, 4);
// Left
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 8, 4);
// Right
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 12, 4);
// Top
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 16, 4);
// Right
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 20, 4);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}

Install the package Api demos and have a look at the example Touch Rotate in
Api demos > Graphics > OpenGL ES > Touch Rotate
You can reach the source code at
android-sdk-linux/samples/android-version/ApiDemos/

Related

Android OpenGL ES 2.0 only partially drawing

I've recently started looking into OpenGL on Android. After T tried WebGL, I tried to use that on Android and ran into a weird issue which I can't solve after hours of googling and trial'n'error.
My code is supposed to draw a cube. However, it seems to not properly use my element buffer and always draws a black/green triangle. Even if I remove some indices, it still draws the same black/green triangle which hints to me that OpenGL pulls the wrong data.
I've read the tutorial on google code, which writes the buffers before every draw call, but I really want to avoid that, due to the memory overhead.
This is the code for my renderer. I expect my error somewhere in here:
package test.slikey.opengl_test;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import static android.opengl.GLES20.*;
public class OpenGLRenderer implements GLSurfaceView.Renderer {
private final String vertexShaderCode = "" +
"precision mediump float;" +
"" +
"attribute vec3 aVertexPosition;" +
"attribute vec4 aVertexColor;" +
"" +
"uniform mat4 uMatWorld;" +
"uniform mat4 uMatView;" +
"uniform mat4 uMatProj;" +
"" +
"varying vec4 vFragColor;" +
"" +
"void main()" +
"{" +
" gl_Position = uMatProj * uMatView * uMatWorld * vec4(aVertexPosition, 1.0);" +
" vFragColor = aVertexColor;" +
"}";
private final String fragmentShaderCode = "" +
"precision mediump float;" +
"" +
"varying vec4 vFragColor;" +
"" +
"void main()" +
"{" +
" gl_FragColor = vFragColor;" +
"}";
private final float[] positions = new float[]{
-1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f, 0.5f, 0.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 0.5f, 0.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
private final byte[] indices = new byte[]{
0, 4, 5,
0, 5, 1,
1, 5, 6,
1, 6, 2,
2, 6, 7,
2, 7, 3,
3, 7, 4,
3, 4, 0,
4, 7, 6,
4, 6, 5,
3, 0, 1,
3, 1, 2
};
private int shaderProgram;
private int attribVertexPosition;
private int attribVertexColor;
private int uniformMatWorld;
private int uniformMatView;
private int uniformMatProj;
private float[] matrixWorld;
private float[] matrixView;
private float[] matrixProj;
private int vertexBufferPointer;
private int indexBufferPointer;
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
glClearColor(0.2f, 0.6f, 0.8f, 1.0f);
shaderProgram = initShaderProgram();
attribVertexPosition = glGetAttribLocation(shaderProgram, "aVertexPosition");
attribVertexColor = glGetAttribLocation(shaderProgram, "aVertexColor");
uniformMatWorld = glGetUniformLocation(shaderProgram, "uMatWorld");
uniformMatView = glGetUniformLocation(shaderProgram, "uMatView");
uniformMatProj = glGetUniformLocation(shaderProgram, "uMatProj");
matrixWorld = new float[16];
matrixView = new float[16];
matrixProj = new float[16];
initBuffers();
}
private int initShaderProgram() {
int vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
int program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
int[] linkStatus = new int[1];
glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GL_TRUE) {
glDeleteProgram(program);
throw new RuntimeException("Could not link program: "
+ glGetProgramInfoLog(program));
}
return program;
}
private int loadShader(int type, String shaderCode) {
int shader = glCreateShader(type);
glShaderSource(shader, shaderCode);
glCompileShader(shader);
int[] compiled = new int[1];
glGetShaderiv(shader, GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
glDeleteShader(shader);
throw new RuntimeException("Could not compile program: "
+ glGetShaderInfoLog(shader) + " | " + shaderCode);
}
return shader;
}
private void initBuffers() {
int[] buffers = new int[2];
glGenBuffers(2, buffers, 0);
vertexBufferPointer = buffers[0];
indexBufferPointer = buffers[1];
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferPointer);
glBufferData(GL_ARRAY_BUFFER, positions.length, ByteBuffer.allocateDirect(positions.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(positions).position(0), GL_STATIC_DRAW);
glVertexAttribPointer(attribVertexPosition, 3, GL_FLOAT, false, 7 * 4, 0);
glVertexAttribPointer(attribVertexColor, 4, GL_FLOAT, false, 7 * 4, 3 * 4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferPointer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.length, ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder()).put(indices).position(0), GL_STATIC_DRAW);
glEnableVertexAttribArray(attribVertexPosition);
glEnableVertexAttribArray(attribVertexColor);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
glViewport(0, 0, width, height);
Matrix.perspectiveM(matrixProj, 0, 45, (float) width / height, 0.01f, 1000.0f);
}
#Override
public void onDrawFrame(GL10 gl) {
glUseProgram(shaderProgram);
Matrix.setIdentityM(matrixWorld, 0);
Matrix.setLookAtM(matrixView, 0,
0, 0, -8,
0, 0, 0,
0, 1, 0
);
glUniformMatrix4fv(uniformMatWorld, 1, false, matrixWorld, 0);
glUniformMatrix4fv(uniformMatView, 1, false, matrixView, 0);
glUniformMatrix4fv(uniformMatProj, 1, false, matrixProj, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_BYTE, 0);
}
}
I expect it to be something really minor, like a default instuction which I am missing which is specific to Android. A similiar code has worked for WebGL.
Hopefully someone has an idea.
Thank you!

Android OpenGL-ES-2.0 Circle or disc

I'm trying to draw a disc in OpenGL-ES 2.0. Based on the second answer to this question How to draw basic circle in OpenGL ES 2.0 Android by user2901066, I'm doing:
String VertexShaderCode ="uniform mat4 uMVPMatrix;\n" +
"attribute vec4 vPosition;\n" +
"void main() {\n" +
"gl_Position = uMVPMatrix * vPosition;\n" +
"}";
String FragmentShaderCode = "precision mediump float;\n" +
"void main() {\n" +
//The problem is here
//"if ((textureCoord.x * textureCoord.x) + (textureCoord.y * textureCoord.y) <= 1.0)" +
"if (true)\n" +
"gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n" +
"else\n" +
"gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 0.0f);\n" +
"}";
int vertexShader = this.loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
int fragmentShader = this.loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);
mGlProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mGlProgram, vertexShader);
GLES20.glAttachShader(mGlProgram, fragmentShader);
GLES20.glLinkProgram(mGlProgram);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
protected int PositionHandle;
protected int MVPMatrixHandle;
static final int COORDS_PER_VERTEX = 3;
private final int VertexStride = COORDS_PER_VERTEX * 4;
private float LineCoords[] = new float[4 * 3];
private FloatBuffer VertexBuffer;
private final int VertexCount = 4;
ByteBuffer bb = ByteBuffer.allocateDirect(LineCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
VertexBuffer = bb.asFloatBuffer();
VertexBuffer.put(LineCoords);
VertexBuffer.position(0);
float[] mvpMatrix = {1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};
LineCoords[0] = -1.0f;
LineCoords[1] = 1.0f;
LineCoords[3] = -1.0f;
LineCoords[4] = -1.0f;
LineCoords[6] = 1.0f;
LineCoords[7] = -1.0f;
LineCoords[9] = 1.0f;
LineCoords[10] = 1.0f;
VertexBuffer.put(LineCoords);
VertexBuffer.position(0);
GLES20.glUseProgram(mGlProgram);
PositionHandle = GLES20.glGetAttribLocation(mGlProgram, "vPosition");
GLES20.glEnableVertexAttribArray(PositionHandle);
GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VertexStride, VertexBuffer);
MVPMatrixHandle = GLES20.glGetUniformLocation(mGlProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, VertexCount);
GLES20.glDisableVertexAttribArray(PositionHandle);
My problem is to get the position in the fragment shader in order to apply the right color. How do I do that?
You need a varying variable declared on both shaders:
varying vec2 textureCoord;
then on the vertex shader, put some value to it such as:
textureCoord = gl_Position.xy;
this variable will then be sent to the fragment shader interpolated for each fragment so your fragment shader can use it:
if ((textureCoord.x * textureCoord.x) + (textureCoord.y * textureCoord.y) <= 1.0)
{
gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
} else {
gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 0.0f);
}

Android OpenGL ES 2.0 - Rotation in place

I would like to rotate my triangles in Z axis, but I would to do it around the center of the triangle, not the center of the screen. I have researched a lot on that but didn't find any resolution.
Any idea of what could I try to solve it?
public class RendererClass implements Renderer {
FloatBuffer bufferObj1;
FloatBuffer bufferObj2;
int programObj1;
int programObj2;
int positionObj1;
int positionObj2;
int rotationMatrixLocationObj1;
int rotationMatrixLocationObj2;
int colorObj1;
int colorObj2;
float[] rotationMatrixObj1 = new float[16];
float[] rotationMatrixObj2 = new float[16];
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config) {
GLES20.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
float[] vertexObj1 = {
-0.8f, 0.8f,
-0.8f, 0.0f,
0.0f, 0.0f
};
float[] vertexObj2 = {
0.8f, 0.8f,
0.8f, 0.0f,
0.0f, 0.0f
};
bufferObj1 = ByteBuffer.allocateDirect(vertexObj1.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexObj1);
bufferObj2 = ByteBuffer.allocateDirect(vertexObj2.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexObj2);
String vssObj1 = "attribute vec4 positionObj1;" +
"uniform mat4 rotationMatrixObj1;" +
"void main(){" +
"gl_Position = rotationMatrixObj1 * positionObj1;" +
"}";
String vssObj2 = "attribute vec4 positionObj2;" +
"uniform mat4 rotationMatrixObj2;" +
"void main(){" +
"gl_Position = rotationMatrixObj2 * positionObj2;" +
"}";
String fssObj1 = "precision mediump float;" +
"uniform vec4 colorObj1;" +
"void main(){" +
"gl_FragColor = colorObj1;" +
"}";
String fssObj2 = "precision mediump float;" +
"uniform vec4 colorObj2;" +
"void main(){" +
"gl_FragColor = colorObj2;" +
"}";
int vsObj1 = glCreateShader(GL_VERTEX_SHADER);
int vsObj2 = glCreateShader(GL_VERTEX_SHADER);
int fsObj1 = glCreateShader(GL_FRAGMENT_SHADER);
int fsObj2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vsObj1, vssObj1);
glShaderSource(vsObj2, vssObj2);
glShaderSource(fsObj1, fssObj1);
glShaderSource(fsObj2, fssObj2);
glCompileShader(vsObj1);
glCompileShader(vsObj2);
glCompileShader(fsObj1);
glCompileShader(fsObj2);
programObj1 = glCreateProgram();
programObj2 = glCreateProgram();
glAttachShader(programObj1, vsObj1);
glAttachShader(programObj2, vsObj2);
glAttachShader(programObj1, fsObj1);
glAttachShader(programObj2, fsObj2);
glLinkProgram(programObj1);
glLinkProgram(programObj2);
positionObj1 = glGetAttribLocation(programObj1, "positionObj1");
positionObj2 = glGetAttribLocation(programObj2, "positionObj2");
rotationMatrixLocationObj1 = glGetUniformLocation(programObj1, "rotationMatrixObj1");
rotationMatrixLocationObj2 = glGetUniformLocation(programObj2, "rotationMatrixObj2");
colorObj1 = glGetUniformLocation(programObj1, "colorObj1");
colorObj2 = glGetUniformLocation(programObj2, "colorObj2");
}
#Override
public void onSurfaceChanged(GL10 arg0, int width, int height) {
Matrix.setIdentityM(rotationMatrixObj1, 0);
Matrix.rotateM(rotationMatrixObj1, 0, MainActivity.angle, 0, 0, 1);
Matrix.setIdentityM(rotationMatrixObj2, 0);
Matrix.rotateM(rotationMatrixObj2, 0, MainActivity.angle, 0, 0, -1);
}
GL10 gl;
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
onSurfaceChanged(gl, 0, 0);
glUseProgram(programObj1);
bufferObj1.position(0);
glVertexAttribPointer(positionObj1, 2, GL_FLOAT, false, 0, bufferObj1);
glEnableVertexAttribArray(positionObj1);
glUniform4f(colorObj1, 0.0f, 0.0f, 1.0f, 1.0f);
glUniformMatrix4fv(rotationMatrixLocationObj1, 1, false, rotationMatrixObj1, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(programObj2);
bufferObj2.position(0);
glVertexAttribPointer(positionObj2, 2, GL_FLOAT, false, 0, bufferObj2);
glEnableVertexAttribArray(positionObj2);
glUniform4f(colorObj2, 1.0f, 0.0f, 0.0f, 1.0f);
glUniformMatrix4fv(rotationMatrixLocationObj2, 1, false, rotationMatrixObj2, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}
You use glDrawArrays so you can alter your triangles in your code any way you want. Use simple trigonometry to rotate your vertices independently.
Rotation matrix rotates vertices around center of coordinate system.
If you want to rotate scene around some other point (x0, y0, z0) you have to do this in 3 simple steps:
translate scene in such way that your point will be in center of coord system (by -x0, -y0, -z0)
rotate
translate back (by x0, y0, z0)
Of course 3 steps of transformation are not needed, matrix multiplication can do this work for us.

Activating/using GL_TEXTURE1 at OpenGL ES 2.0 for Android

I'm trying to use the GL_TEXTURE1 texture unit to draw a simple shape. I know how to draw it using the standard GL_TEXTURE0, but when changing it something is not working.
I thought that from my code below, I just had to change the following:
glActiveTexture(GL_TEXTURE1);
glUniform1i(uTextureLocation, 1);
What I'm missing?
Code:
public class RendererClass implements Renderer {
Context context;
FloatBuffer verticesInBuffer;
int aPositionLocation;
int aTextureLocation;
int uTextureLocation;
int program;
public RendererClass(Context context){
this.context = context;
}
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
float[] vertices = {
-0.5f, 0.5f, 0.5f, 0.5f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 0.0f, 0.0f, 0.0f
};
verticesInBuffer = ByteBuffer.allocateDirect(vertices.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertices);
String vss = "attribute vec4 a_Position;" +
"attribute vec2 a_Texture;" +
"varying vec2 v_Texture;" +
"void main(){" +
" v_Texture = a_Texture;" +
" gl_Position = a_Position;" +
"}";
String fss = "precision mediump float;" +
"varying vec2 v_Texture;" +
"uniform sampler2D u_Texture;" +
"void main(){" +
" gl_FragColor = texture2D(u_Texture, v_Texture);" +
"}";
int vs = glCreateShader(GL_VERTEX_SHADER);
int fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vs, vss);
glShaderSource(fs, fss);
glCompileShader(vs);
glCompileShader(fs);
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
aPositionLocation = glGetAttribLocation(program, "a_Position");
// ***** Texture stuff starts here </</</</
// Fase 1
glActiveTexture(GL_TEXTURE0);
int[] genTextures = new int[1];
glGenTextures(1, genTextures, 0);
glBindTexture(GL_TEXTURE_2D, genTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Fase 2
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.res_for_test_1, options);
// Fase 3
texImage2D(GL_TEXTURE_2D, 0, bitmap1, 0);
glGenerateMipmap(GL_TEXTURE_2D);
// Fase 4
aTextureLocation = glGetAttribLocation(program, "a_Texture");
uTextureLocation = glGetUniformLocation(program, "u_Texture");
glUniform1i(uTextureLocation, 0);
verticesInBuffer.position(2);
glEnableVertexAttribArray(aTextureLocation);
glVertexAttribPointer(aTextureLocation, 2, GL_FLOAT, false, 16, verticesInBuffer);
// ***** Texture stuff ends here </</</</
}
#Override
public void onSurfaceChanged(GL10 arg0, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
glUseProgram(program);
verticesInBuffer.position(0);
glEnableVertexAttribArray(aPositionLocation);
glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 16, verticesInBuffer);
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
}
}
You need to specify active texture unit and assign a previously loaded texture to it.
For convenience, I've created a helper function which does all of this. It activates given texture unit, assigns texture with given ID to it and puts this value to sampler2D uniform of shader:
protected void setTexture2D(int textureUnit, int textureID, int uniformID) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + textureUnit);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
GLES20.glUniform1i(uniformID, textureUnit);
}
And then call it like this:
setTexture2D(0, textureID, uniformID);

Android Opengl: Only front face of my 3D cube is shown

I am trying to draw a 3D cube using OpenGL ES2, and my code is only drawing the front side (a square) of the cube as shown in this image. I can't figure out whats wrong. I have tried implementing my cube based on other tutorials too but no luck.
What's wrong with my code?..am I missing an improtant line of code somewhere?
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glEnable(GLES20.GL_CULL_FACE);
Matrix.setLookAtM(mVMatrix,0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
}
DrawFrame Method
#Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
//Calling draw method of shapes
square.draw(mMVPMatrix);
}
Cube Class
// x, y, z
static float squareCoords[] = {-1f, -1f, 1f,//Bottom Left
1f, -1f, 1f, //Bottom Right
1f, 1f, 1f, //Top Right
-1f, 1f, 1f, //Top left
-1f, -1f, -1f,//Bottom Left
1f, -1f, -1f, //Bottom Right
1f, 1f, -1f, //Top Right
-1f, 1f, -1f //Top left
};
private short drawOrder[] = {0,1,2, 0,2,3,//front
0,3,7, 0,7,4,//Left
0,1,5, 0,5,4,//Bottom
6,7,4, 6,4,5,//Back
6,7,3, 6,3,2,//top
6,2,1, 6,1,5//right
}; //Order to draw vertices
private int vertaxCount = 0; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z)
private int vertaxStride = 0; //4 are how many bytes in a float
private float [] color = new float[]{
0.1f, 0.5f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 10.0f, 0.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
public Square()
{
//initialising vertex byte buffer for shape coordinates
// (number of coordinate values * 4 bytes per float)
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
//Initialise byte buffer for the draw list
//(number of draw values * 2 bytes per short )
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer colors = ByteBuffer.allocateDirect(color.length * 4);
colors.order(ByteOrder.nativeOrder());
bufferColor = colors.asFloatBuffer();
bufferColor.put(color);
bufferColor.position(0);
int vertexShader = Shaders.loadShader(GLES20.GL_VERTEX_SHADER, Shaders.vertexShaderCode);
int fragmentShader = Shaders.loadShader(GLES20.GL_FRAGMENT_SHADER, Shaders.fragmentShaderCode);
mProg = GLES20.glCreateProgram();
GLES20.glAttachShader(mProg, vertexShader);
GLES20.glAttachShader(mProg, fragmentShader);
GLES20.glLinkProgram(mProg);
vertaxCount = squareCoords.length / COORDS_PER_VERTEX; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z)
vertaxStride = COORDS_PER_VERTEX * 4; //4 are how many bytes in a float
}
public void draw(float[] mMVPMatrix)
{
//Add program to OpenGL environment
GLES20.glUseProgram(mProg);
//Get Handle to the vertices
int mPositionHandle = GLES20.glGetAttribLocation(mProg, "vPosition");
//Prepare the shape coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertaxStride, vertexBuffer);
//Enable a handle to the shape vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
int mColorHandle = GLES20.glGetUniformLocation(mProg, "v_color");
GLES20.glVertexAttribPointer(mColorHandle, 3, GLES20.GL_FLOAT, false, 0, bufferColor);
GLES20.glEnableVertexAttribArray(mColorHandle);
float [] tm = new float[16];
float [] rm = new float[16];
Matrix.scaleM(mMVPMatrix, 0, 0.35f, 0.35f, 0);
Matrix.translateM(tm, 0, mMVPMatrix, 0, 0f, 0f, 0);
Matrix.rotateM(rm, 0, tm, 0, 45f, 0, 0, 1);
// get handle to shape's transformation matrix
int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProg, "u_MVPMatrix");
// Apply the projection and view transformation
//GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, rm, 0);
//Draw the shape
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertaxCount);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
//Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
class Cube {
private FloatBuffer mVertexBuffer;
private FloatBuffer mColorBuffer;
private ShortBuffer mIndexBuffer;
private int mProgram, mPositionHandle, mColorHandle, mMVPMatrixHandle ;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec4 aColor;" +
"varying vec4 vColor;" +
"void main() {" +
"vColor = aColor;" +
"gl_Position = vPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 vColor;" +
"void main() {" +
"gl_FragColor = vColor;" + // vec4(0.0, 1.0, 0.0, 1.0);" +
"}";
private float vertices[] = {
-0.5f, -0.5f, 0.5f,//Bottom Left
0.5f, -0.5f, 0.5f, //Bottom Right
0.5f, 0.5f, 0.5f, //Top Right
-0.5f, 0.5f, 0.5f, //Top left
-0.5f, -0.5f, -0.5f,//Bottom Left
0.5f, -0.5f, -0.5f, //Bottom Right
0.5f, 0.5f, -0.5f, //Top Right
-0.5f, 0.5f, -0.5f //Top left
};
private float colors[] = {
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f
};
private short indices[] = {
0,1,2, 0,2,3,//front
0,3,7, 0,7,4,//Left
0,1,5, 0,5,4,//Bottom
6,7,4, 6,4,5,//Back
6,7,3, 6,3,2,//top
6,2,1, 6,1,5//right
};
public Cube() {
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mVertexBuffer = byteBuf.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(colors.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mColorBuffer = byteBuf.asFloatBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(indices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mIndexBuffer = byteBuf.asShortBuffer();
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram);
}
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void draw (float[] mvpMatrix){
//GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
12, mVertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glEnableVertexAttribArray(mColorHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mColorHandle, 4,
GLES20.GL_FLOAT, false,
0, mColorBuffer);
// Set color for drawing the triangle
// GLES20.glUniform2fv(mColorHandle, 1,colors, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mColorHandle);
}
}
public abstract class GLRenderer implements GLSurfaceView.Renderer {
boolean mFirstDraw;
boolean mSurfaceCreated;
int mWidth;
int mHeight;
long mLastTime;
int mFPS;
float[] mProjMatrix = new float[16];
float[] mVMatrix = new float[16];
float[] mMVPMatrix = new float[16];
private float[] rotationMatrix = new float[16];
private float angle = 0f;
GLRenderer() {
mFirstDraw = true;
mSurfaceCreated = false;
mWidth = -1;
mHeight = -1;
mLastTime = System.currentTimeMillis();
mFPS = 0;
}
#Override
public void onDrawFrame(GL10 arg0) {
// TODO Auto-generated method stub
Cube mCube = new Cube();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
if (mFirstDraw)
mFirstDraw = false;
angle += 0.7f;
if (angle > 360f)
angle = 0f;
Matrix.setLookAtM(mVMatrix, 0, 0f, 0f, 4f, 0f, 0f, 0f, 0f, 1f, 0f);
// projection x view = modelView
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Creating rotation matrix
Matrix.setRotateM(rotationMatrix, 0, angle, 0f, 0f, -1f);
// rotation x camera = modelView
float[] duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);
Matrix.setRotateM(rotationMatrix, 0, angle, 0f, -1f, 0f);
duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);
Matrix.setRotateM(rotationMatrix, 0, angle, -1f, 0f, 0f);
duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);
// rotation x camera = modelView
mCube.draw(mMVPMatrix);
}
#Override
public void onSurfaceChanged(GL10 arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
mWidth = arg1;
mHeight = arg2;
GLES20.glViewport(0, 0, mWidth, mHeight);
float ratio = (float) mWidth / mHeight;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -1, 1, -1, 1, 3, 7);
}
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
// TODO Auto-generated method stub
mSurfaceCreated = true;
mWidth = -1;
mHeight = -1;
GLES20.glClearColor(0f, 0f, 0f, 0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
}
}
public class MainActivity extends Activity {
GLSurfaceView glView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
if(hasGL20()){
glView = new GLSurfaceView(getApplicationContext());
glView.setEGLContextClientVersion(2);
glView.setPreserveEGLContextOnPause(true);
glView.setRenderer(new GL20Renderer());
}else{
Log.v ("No Req Version","");
}
setContentView(glView);
}
#Override
protected void onPause() {
super.onPause();
if(glView != null)
glView.onPause();
}
#Override
protected void onResume() {
super.onResume();
if(glView != null)
glView.onResume();
}
private boolean hasGL20(){
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
return info.reqGlEsVersion >= 0x20000;
}
}
It could be that your triangles are not all wound in a consistent direction. Try disabling backface culling:
GLES20.glDisable(GLES20.GL_CULL_FACE);
Or, reverse the CullFace to front:
GLES20.glCullFace(GLES20.GL_FRONT);
If this changes which sides of the cube are rendered, then your triangles are not all wound in a consistent direction.

Categories

Resources