本节我们继续来看一下《OPENGL ES 3.0编程指南 原书第2版(中文版)》书中第8章的内容,PDF下载地址:OPENGL ES 3.0编程指南 原书第2版(中文版),代码下载地址:Opengl ES Source Code。该书中好像没有对Demo的代码进行讲解,全书的重点全部都集中在Opengl ES本身,而实现出来的实例代码讲解的很少,作为初学者,理解起来确实比较费劲,这也是我为什么推荐大家先学习2.0的原因,2.0的那本书对实现出来的Demo的代码全部进行了讲解,我们就知道要实现一个功能,需要什么样的步骤,每一步是什么意思,这样比较清晰。
还是来看一下本节最终实现的效果,效果图如下,是一个纯色的立方体,在不断的旋转:
我们对照代码来看一下,先来看一下SimpleVertexShaderRenderer类,源码如下:
public class SimpleVertexShaderRenderer implements GLSurfaceView.Renderer {
private Context mContext;
private final float[] projectionMatrix = new float[16];
private final float[] viewMatrix = new float[16];
private final float[] viewProjectionMatrix = new float[16];
private FloatBuffer mMatrixFloatBuffer;
///
// Constructor
//
public SimpleVertexShaderRenderer(Context context) {
mContext = context;
}
///
// Initialize the shader and program object
//
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
String vShaderStr = ESShader.readShader(mContext, "chapter8/vertexShader.vert");
String fShaderStr = ESShader.readShader(mContext, "chapter8/fragmentShader.frag");
// Load the shaders and get a linked program object
mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
// Get the uniform locations
mMVPLoc = GLES30.glGetUniformLocation(mProgramObject, "u_mvpMatrix");
// Generate the vertex data
mCube.genCube(0.6f);
// Starting rotation angle for the cube
mAngle = 45.0f;
GLES30.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
mMatrixFloatBuffer = ByteBuffer.allocateDirect(16 * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
}
private void update() {
if (mLastTime == 0) {
mLastTime = SystemClock.uptimeMillis();
}
long curTime = SystemClock.uptimeMillis();
long elapsedTime = curTime - mLastTime;
float deltaTime = elapsedTime / 1000.0f;
mLastTime = curTime;
// ESTransform perspective = new ESTransform();
// ESTransform modelview = new ESTransform();
float aspect;
// Compute a rotation angle based on time to rotate the cube
mAngle += (deltaTime * 40.0f);
if (mAngle >= 360.0f) {
mAngle -= 360.0f;
}
// Compute the window aspect ratio
aspect = (float) mWidth / (float) mHeight;
// Generate a perspective matrix with a 60 degree FOV
// perspective.matrixLoadIdentity();
// Matrix.setIdentityM(viewMatrix, 0);
// perspective.perspective(60.0f, aspect, 1.0f, 20.0f);
Matrix.perspectiveM(projectionMatrix, 0, 60.0f, aspect, 1.0f, 20.0f);
// Generate a model view matrix to rotate/translate the cube
// modelview.matrixLoadIdentity();
Matrix.setIdentityM(viewMatrix, 0);
// Translate away from the viewer
// modelview.translate(0.0f, 0.0f, -2.0f);
Matrix.translateM(viewMatrix, 0, 0.0f, 0.0f, -2.0f);
// Rotate the cube
// modelview.rotate(mAngle, 1.0f, 0.0f, 1.0f);
Matrix.rotateM(viewMatrix, 0, mAngle, 1.0f, 0.0f, 1.0f);
// Compute the final MVP by multiplying the
// modevleiw and perspective matrices together
// mMVPMatrix.matrixMultiply(modelview.get(), perspective.get());
Matrix.multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
mMatrixFloatBuffer.clear();
mMatrixFloatBuffer.put(viewProjectionMatrix).position(0);
}
///
// Draw a triangle using the shader pair created in onSurfaceCreated()
//
public void onDrawFrame(GL10 glUnused) {
update();
// Set the viewport
GLES30.glViewport(0, 0, mWidth, mHeight);
// Clear the color buffer
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
// Use the program object
GLES30.glUseProgram(mProgramObject);
// Load the vertex data
GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false,
0, mCube.getVertices());
GLES30.glEnableVertexAttribArray(0);
// Set the vertex color to red
GLES30.glVertexAttrib4f(1, 1.0f, 0.0f, 0.0f, 1.0f);
// Load the MVP matrix
GLES30.glUniformMatrix4fv(mMVPLoc, 1, false,
mMatrixFloatBuffer);
// Draw the cube
GLES30.glDrawElements(GLES30.GL_TRIANGLES, mCube.getNumIndices(),
GLES30.GL_UNSIGNED_SHORT, mCube.getIndices());
}
///
// Handle surface changes
//
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
mWidth = width;
mHeight = height;
}
// Handle to a program object
private int mProgramObject;
// Uniform locations
private int mMVPLoc;
// Vertex data
// private ESShapes mCube = new ESShapes();
private Cube mCube &