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.
Related
If i change the background of GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f) and then try to draw a texture, colors of this last changes unexpectedly. This is the png file:
The result of the application when i try simply to display it is this one:
Im using this code:
public class GLRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "MyGLRenderer";
private float[] vertices = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f
};
private float[] textureVertices = {
0f, 1f,
1f, 1f,
0f, 0f,
1f, 0f
};
private final String vertexShaderCode =
"attribute vec4 aPosition;" +
"attribute vec2 aTexPosition;" +
"varying vec2 vTexPosition;" +
"void main() {" +
" gl_Position = aPosition;" +
" vTexPosition = aTexPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D uTexture;" +
"varying vec2 vTexPosition;" +
"void main() {\n" +
"vec4 color = texture2D(uTexture, vTexPosition);\n"+
//"if(color.r == 0.0 && color.g == 0.0 && color.b == 0.0)\n"+
// "color = vec4(1.0,0.5,0.5,1.0);"+
// "discard;"+
" gl_FragColor = color;" +
"}";
private FloatBuffer verticesBuffer;
private FloatBuffer textureBuffer;
private int vertexShader;
private int fragmentShader;
private int program;
private Bitmap bmp;
private int textures[] = new int[2];
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
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];
public GLRenderer() {
bmp=Bitmap.createBitmap(513,912, Bitmap.Config.ARGB_8888);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
checkGlError("glClearColor");
setup();
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
#Override
public void onDrawFrame(GL10 gl) {
Log.d("Drawing_Frame","Working");
float[] scratch = new float[16];
// Draw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// Draw Bitmap
drawBinaryImage(bmp,textures[0]);
Matrix.setRotateM(mRotationMatrix, 0, 0, 0, 0, 1.0f);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
}
private void setup(){
GLES20.glGenTextures(2, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
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);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
//GLES20.glBindTexture(GL);
initializeBuffers();
initializeProgram();
}
private void initializeBuffers() {
ByteBuffer buff = ByteBuffer.allocateDirect(vertices.length * 4);
buff.order(ByteOrder.nativeOrder());
verticesBuffer = buff.asFloatBuffer();
verticesBuffer.put(vertices);
verticesBuffer.position(0);
buff = ByteBuffer.allocateDirect(textureVertices.length * 4);
buff.order(ByteOrder.nativeOrder());
textureBuffer = buff.asFloatBuffer();
textureBuffer.put(textureVertices);
textureBuffer.position(0);
}
private void initializeProgram() {
vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glGetShaderInfoLog(vertexShader);
checkGlError("glCreateShader");
GLES20.glShaderSource(vertexShader, vertexShaderCode);
GLES20.glCompileShader(vertexShader);
fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, fragmentShaderCode);
GLES20.glCompileShader(fragmentShader);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
checkGlError("glLinkProgram");
}
public void updateTexture(Bitmap bmp){
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
}
private void drawBinaryImage(Bitmap bmp,int texture){
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glUseProgram(program);
//Changes Here original Line GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
int positionHandle = GLES20.glGetAttribLocation(program, "aPosition");
int textureHandle = GLES20.glGetUniformLocation(program, "uTexture");
int texturePositionHandle = GLES20.glGetAttribLocation(program, "aTexPosition");
//Log.d("GL_SETUP",positionHandle+" , "+textureHandle);
GLES20.glVertexAttribPointer(texturePositionHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glEnableVertexAttribArray(texturePositionHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
Log.d("FILTER_APPLY","Applying");
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glUniform1i(textureHandle, 0);
GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, verticesBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
}
public void setBitmap(Bitmap bitmap){
updateTexture(bitmap);
this.bmp = bitmap;
}
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
The framebuffer is cleared by GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);.
RGBA(1, 1, 0, 1) is yellow. This causes that before rendering the texture, the entire framebuffer is filled in yellow.
The texture contains a blue color RGBA(0, 0, 1, 1) and a black color RGBA(0, 0, 0, 1).
When the quad with the texture is drawn, then blending is enabled with the following function:
(see Blending and glBlendFunc)
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
At blending the current color of the framebuffer is mixed by the actually drawn color. With the above setup this done by the following function:
destinationColor = sourceColor * 1 + destinationColor * 1
In the regions where the texture is blue, the final color becomes white:
(1, 1, 0) * 1 + (0, 0, 1) * 1 = (1, 1, 1)
In the regions where the texture is black, the color in the framebuffer stays yellow:
(1, 1, 0) * 1 + (0, 0, 0) * 1 = (1, 1, 0)
I'm trying to make a program with triangle and circle where triangle should be transparent, and circle needs to move on y axis. I can make circle and triangle, but don't know how to move circle. So I made a square and set it move on the y axis. My question is what is the best way to make a circle with movement, I thought about adding texture to square to look like a circle, but it will apply texture to the triangle as well. Any help would mean so much. Thanks!
Here's my code:
public class MyGLRender implements GLSurfaceView.Renderer{
Context con;
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] projectionMatrix = new float[16];
private float[] mVPMatrix = new float[16];
private final FloatBuffer squareVert;
private final FloatBuffer mColor;
private FloatBuffer triangleVert;
private final FloatBuffer tColor;
private int mvpMatrixHandle;
private int positionHandle;
private int colorHandle;
ShortBuffer indexBuffer = null;
short[] indeces={
0,1,2,
0,3,2
};
float i;
public int smer;
public MyGLRender(Context con)
{
this.con=con;
i=0;
smer=1;
final float[] square={
0.0f, 1.0f, 0.0f,
0.0f,0.0f,0.0f,
1.0f,0.0f,0.0f,
1.0f,1.0f,0.0f,
};
final float[] triangle={
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
final float[] colors = {1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1
};
final float[] colorsTr = {1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1
};
squareVert = ByteBuffer.allocateDirect(square.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
squareVert.put(square).position(0);
indexBuffer = ByteBuffer.allocateDirect(indeces.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
indexBuffer.put(indeces).position(0);
mColor = ByteBuffer.allocateDirect(colors.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mColor.put(colors).position(0);
triangleVert = ByteBuffer.allocateDirect(square.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
triangleVert.put(triangle).position(0);
indexBuffer = ByteBuffer.allocateDirect(indeces.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
indexBuffer.put(indeces).position(0);
tColor = ByteBuffer.allocateDirect(colors.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
tColor.put(colorsTr).position(0);
}
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5, 0, 0, 0, 0, 1, 0);
final String vertexShader =
"uniform mat4 un_MVPMatrix; \n"
+ "attribute vec4 attribute_Position; \n"
+ "attribute vec4 attribute_Color; \n"
+ "varying vec4 var_Color; \n"
+ "void main() \n"
+ "{ \n"
+ " var_Color = attribute_Color; \n"
+ " gl_Position = un_MVPMatrix \n"
+ " * attribute_Position; \n"
+ "} \n";
final String fragmentShader =
"precision mediump float; \n"
+ "varying vec4 var_Color; \n"
+ "void main() \n"
+ "{ \n"
+
" gl_FragColor = (length(gl_FragCoord.xy) < 0.5 ) \n" +
" ? vec4(1.0, 1.0, 1.0, 1.0)\n" +
" : vec4(0.5, 0.5, 0.5, 0.5); \n"
+ "} \n";
int vertexS = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexS != 0)
{
GLES20.glShaderSource(vertexS, vertexShader);
GLES20.glCompileShader(vertexS);
final int[] compile_Status = new int[1];
GLES20.glGetShaderiv(vertexS, GLES20.GL_COMPILE_STATUS, compile_Status, 0);
}
if (vertexS == 0)
{
try {
throw new Exception("Vertex shader is not created.");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int fragmentS = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentS != 0)
{
GLES20.glShaderSource(fragmentS, fragmentShader);
GLES20.glCompileShader(fragmentS);
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentS, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
}
if (fragmentS == 0)
{
try {
throw new Exception("Fragment shader is not created.");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int program = GLES20.glCreateProgram();
if (program != 0)
{
GLES20.glAttachShader(program, vertexS);
GLES20.glAttachShader(program, fragmentS);
GLES20.glBindAttribLocation(program, 0, "attribute_Position");
GLES20.glBindAttribLocation(program, 1, "attribute_Color");
GLES20.glLinkProgram(program);
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
}
if (program == 0)
{
try {
throw new Exception("Program error");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mvpMatrixHandle = GLES20.glGetUniformLocation(program, "un_MVPMatrix");
positionHandle = GLES20.glGetAttribLocation(program, "attribute_Position");
colorHandle = GLES20.glGetAttribLocation(program, "attribute_Color");
GLES20.glUseProgram(program);
}
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
GLES20.glViewport(0, 0, width, height);
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(projectionMatrix, 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);
if (i > 1) {
smer = -1;
}
if (i < -1) {
smer = 1;
}
i += 0.05 * smer;
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0, i, 0.0f);
drawSqare(squareVert, indexBuffer);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix,0, -1.5f, 0.0f, 0.0f);
drawSTriangle(triangleVert, indexBuffer);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, -1.0f, 0.0f, -0.0f);
drawSTriangle(triangleVert, indexBuffer);
GLES20.glDisable(GLES20.GL_BLEND);
}
private void drawSqare(final FloatBuffer aTriangleBuffer,ShortBuffer sb)
{
aTriangleBuffer.position(0);
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
mColor.position(0);
GLES20.glVertexAttribPointer(colorHandle, 3, GLES20.GL_FLOAT, false, 0, mColor);
GLES20.glEnableVertexAttribArray(colorHandle);
Matrix.multiplyMM(mVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mVPMatrix, 0, projectionMatrix, 0, mVPMatrix, 0);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indeces.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}
private void drawSTriangle(final FloatBuffer fbb,ShortBuffer sbb)
{
fbb.position(0);
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, fbb);
GLES20.glEnableVertexAttribArray(positionHandle);
tColor.position(0);
GLES20.glVertexAttribPointer(colorHandle, 3, GLES20.GL_FLOAT, false,
0, tColor);
GLES20.glEnableVertexAttribArray(colorHandle);
Matrix.multiplyMM(mVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mVPMatrix, 0, projectionMatrix, 0, mVPMatrix, 0);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indeces.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}
}
You can follow the Documentation provided by Android for OpenGL
Check this for adding Rotation or motion to view.
here is the sample from Android http://developer.android.com/shareables/training/OpenGLES.zip
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);
ive made a skybox with the following class and the image comes out blurry in some parts of the sky and the grass, im trying to figure out how to fix it, thank you for your time.
public class SkyBox {
private static final String TAG = "skybox";
private FloatBuffer vertexBuffer; // Vertex Buffer
private FloatBuffer texBuffer; // Texture Coords Buffer
private int numFaces = 6;
private int[] imageFileIDs = { // Image file IDs
R.drawable.skybox,
R.drawable.skybox1,
R.drawable.skybox2,
R.drawable.skybox3,
R.drawable.skybox4,
R.drawable.skybox5
};
private int[] textureIDs = new int[numFaces];
private Bitmap[] bitmap = new Bitmap[numFaces];
private float cubeHalfSize = 2f;
// Constructor - Set up the vertex buffer
public SkyBox(Context context) {
// Allocate vertex buffer. An float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
// Read images. Find the aspect ratio and adjust the vertices accordingly.
for (int face = 0; face < numFaces; face++) {
bitmap[face] = BitmapFactory.decodeStream(
context.getResources().openRawResource(imageFileIDs[face]));
int imgWidth = bitmap[face].getWidth();
int imgHeight = bitmap[face].getHeight();
float faceWidth = 2.0f;
float faceHeight = 2.0f;
// Adjust for aspect ratio
faceHeight = faceHeight * imgHeight / imgWidth;
faceWidth = faceWidth * imgWidth / imgHeight;
float faceLeft = -faceWidth*20;
float faceRight = -faceLeft;
float faceTop = faceHeight*20;
float faceBottom = -faceTop;
// Define the vertices for this face
float[] vertices = {
faceLeft, faceBottom, 0.0f, // 0. left-bottom-front
faceRight, faceBottom, 0.0f, // 1. right-bottom-front
faceLeft, faceTop, 0.0f, // 2. left-top-front
faceRight, faceTop, 0.0f, // 3. right-top-front
};
vertexBuffer.put(vertices); // Populate
}
vertexBuffer.position(0); // Rewind
// Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces.
float[] texCoords = {
0.0f, 1.0f, // A. left-bottom
1.0f, 1.0f, // B. right-bottom
0.0f, 0.0f, // C. left-top
1.0f, 0.0f // D. right-top
};
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces);
tbb.order(ByteOrder.nativeOrder());
texBuffer = tbb.asFloatBuffer();
for (int face = 0; face < numFaces; face++) {
texBuffer.put(texCoords);
}
texBuffer.position(0); // Rewind
}
// Render the shape
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer);
// front
gl.glPushMatrix();
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// left
gl.glPushMatrix();
gl.glRotatef(270.0f, 0f, 1f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[1]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
gl.glPopMatrix();
// back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0f, 1f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[2]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
gl.glPopMatrix();
// right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0f, 1f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[3]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
gl.glPopMatrix();
// top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1f, 0f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[4]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
gl.glPopMatrix();
// bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1f, 0f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[5]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
// Load images into 6 GL textures
public void loadTexture(GL10 gl) {
gl.glGenTextures(6, textureIDs, 0); // Generate texture-ID array for 6 IDs
Log.d(TAG, "gen number = " + textureIDs[0]);
// Generate OpenGL texture images
for (int face = 0; face < numFaces; face++) {
Log.d(TAG, "gen number " + face + " = " + textureIDs[face]);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST_MIPMAP_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Build Texture from loaded bitmap for the currently-bind texture ID
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0);
bitmap[face].recycle();
}
}
}
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/