본문 바로가기

카테고리 없음

안드로이드 OpenGL ES 2 예제, 사각형 그리기

안드로이드 OpenGL ES 2에서 Vertex Shader, Fragment Shader를 이용하여 4각형을 화면에 출력하는 예

아래의 예제를 실제 기기에서 실행하면 다음과 같은 결과를 확인할 수 있다

Activity class

package gl.test1;


import android.app.Activity;

import android.app.ActivityManager;

import android.content.Context;

import android.content.pm.ConfigurationInfo;

import android.opengl.GLSurfaceView;

import android.os.Bundle;

import android.view.MotionEvent;


public class OpenGLES2SquareActivity extends Activity {


private GLSurfaceView mGLSurfaceView;


@Override

public void onCreate(Bundle savedInstanceState) 

{

super.onCreate(savedInstanceState);

mGLSurfaceView = new GLSurfaceView(this);


// Check if the system supports OpenGL ES 2.0.

final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();

final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;


if (supportsEs2) 

{

// Request an OpenGL ES 2.0 compatible context.

mGLSurfaceView.setEGLContextClientVersion(2);


// Set the renderer to our demo renderer, defined below.

mGLSurfaceView.setRenderer(new SquareRenderer());

else 

{

// This is where you could create an OpenGL ES 1.x compatible

// renderer if you wanted to support both ES 1 and ES 2.

return;

}


setContentView(mGLSurfaceView);

}


@Override

protected void onResume() 

{

// The activity must call the GL surface view's onResume() on activity onResume().

super.onResume();

mGLSurfaceView.onResume();

}


@Override

protected void onPause() 

{

// The activity must call the GL surface view's onPause() on activity onPause().

super.onPause();

mGLSurfaceView.onPause();

}

}


SquareRenderer

package gl.test1;


import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.nio.FloatBuffer;


import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.opengles.GL10;


import android.opengl.GLES20;

import android.opengl.Matrix;

import android.opengl.GLSurfaceView.Renderer;


public class SquareRenderer implements Renderer {

public float mAngle;

private int mProgram;    

private int maPositionHandle;

private FloatBuffer vbuf;

private int muMVPMatrixHandle;    

private float[] mMVPMatrix = new float[16];    

private float[] mMMatrix = new float[16];    

private float[] mVMatrix = new float[16];    

private float[] mProjMatrix = new float[16];

private final String vertexShaderCode =         

"uniform mat4 uMVPMatrix;  \n" +

"attribute vec4 aPosition; \n" +        

"void main(){              \n" +        

" gl_Position = uMVPMatrix * aPosition; \n" +        

"}                         \n";

private final String fragmentShaderCode =         

"precision mediump float;  \n" +        

"void main(){              \n" +        

" gl_FragColor = vec4 (0, 0.5, 0, 1.0); \n" +        

"}                         \n";

@Override

public void onDrawFrame(GL10 unused) {


GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT );

//glUseProgram

// Add program to OpenGL environment        

GLES20.glUseProgram(mProgram);                

// Prepare the square data        

GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 12, vbuf);        

GLES20.glEnableVertexAttribArray(maPositionHandle);   

//Matrix.setIdentityM(mMMatrix, 0);

Matrix.setRotateM(mMMatrix, 0, mAngle, 0, 0, 1.0f);

Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);        

Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);                

// Apply a ModelView Projection transformation        

GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 

// Draw the square(2개의 삼각형이므로 정점은 6개)        

GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);

}


@Override

public void onSurfaceChanged(GL10 unused, int width, int height) {

GLES20.glViewport(0,0,width,height);

float ratio = (float) width/height;

//this projection matrix is applied to object coodinates

//in the onDrawFrame() method

Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); // docs

muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

}


@Override

public void onSurfaceCreated(GL10 unused, EGLConfig config) {

GLES20.glClearColor(0.0f,0.0f,0.0f,1.0f);

initShapes();

int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);        

int fragmentShader = 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);                  // creates OpenGL program executables                

// get handle to the vertex shader's vPosition member        

maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");

}

private int loadShader(int type, String shaderCode){            

// create a vertex shader type (GLES20.GL_VERTEX_SHADER)        

// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)        

int shader = GLES20.glCreateShader(type);                 

// add the source code to the shader and compile it        

GLES20.glShaderSource(shader, shaderCode);        

GLES20.glCompileShader(shader);                

return shader;    

}

private void initShapes(){            

float squareCoords[] = {            

// X, Y, Z            

-0.5f, 0.5f, 0f,

-0.5f, -0.5f, 0f,

0.5f, -0.5f, 0f,

-0.5f, 0.5f, 0f,

0.5f, -0.5f, 0f,

0.5f, 0.5f, 0f

};                 

// initialize vertex Buffer for triangle          

ByteBuffer vbb = ByteBuffer.allocateDirect(squareCoords.length * 4);

vbb.order(ByteOrder.nativeOrder()); // use the device hardware's native byte order

vbuf = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer  

vbuf.put(squareCoords); // add the coordinates to the FloatBuffer    

vbuf.position(0); // set the buffer to read the first coordinate            

}

}