編輯:關於Android編程
(圖一)
在Opengl中攝像頭包含三部分的信息:
1. 攝像頭的位置 ,在三維空間中用 x y z 表示
2. 攝像頭的鏡頭的指向,這裡即觀察的物體的坐標,一般選取物體的center坐標(通過攝像頭的位置與觀察的物體的坐標可以確定一個向量,這個向量就可以決定觀察的方向)
3. 攝像頭的UP方向,攝像機頂端的指向
下面的人眼觀察物體的圖示更容易幫助我們理解:
(圖二 )
可以看出攝像機的位置,朝向,UP方向有很多不同的組合,對於不同的組合觀察同一物體會得到不同的結果
為了更好地理解,這裡給出國外大牛做的一個demo :
我們先做只需要看gluLookAt , eye 就是我們所說的攝像機的位置,center即攝像頭的鏡頭的指向
我們可以改變這些值,來觀察一下右上方的圖像的變化。
下載地址:http://download.csdn.net/detail/cassiepython/9541794
(圖三)
其中,視點指攝像機的位置,近平面指距離視點較近的垂直於觀察方向的平面,視景體又叫做視錐體為椎台形區域。
透視投影的投影線互不平行,相較於視點,因此,對於同樣尺寸的物體,在近處投影出來大,在遠處投影出來小,由此產生近大遠小的效果。
(圖四)
大家可以繼續結合上面的小軟件修改參數試下來了解透視投影。
package com.cumt.shape;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.content.Context;
public class Cube {
private FloatBuffer vertexBuffer;
private Context context;
//float類型的字節數
private static final int BYTES_PER_FLOAT = 4;
static float vertices[] = {
//前面
0,0,1.0f,
1.0f,1.0f,1.0f,
-1.0f,1.0f,1.0f,
0,0,1.0f,
-1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,0,1.0f,
-1.0f,-1.0f,1.0f,
1.0f,-1.0f,1.0f,
0,0,1.0f,
1.0f,-1.0f,1.0f,
1.0f,1.0f,1.0f,
//後面
0,0,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,0,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
0,0,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,0,-1.0f,
-1.0f,1.0f,-1.0f,
1.0f,1.0f,-1.0f,
//左面
-1.0f,0,0,
-1.0f,1.0f,1.0f,
-1.0f,1.0f,-1.0f,
-1.0f,0,0,
-1.0f,1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,0,0,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,1.0f,
-1.0f,0,0,
-1.0f,-1.0f,1.0f,
-1.0f,1.0f,1.0f,
//右面
1.0f,0,0,
1.0f,1.0f,1.0f,
1.0f,-1.0f,1.0f,
1.0f,0,0,
1.0f,-1.0f,1.0f,
1.0f,-1.0f,-1.0f,
1.0f,0,0,
1.0f,-1.0f,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,0,0,
1.0f,1.0f,-1.0f,
1.0f,1.0f,1.0f,
//上面
0,1.0f,0,
1.0f,1.0f,1.0f,
1.0f,1.0f,-1.0f,
0,1.0f,0,
1.0f,1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,1.0f,0,
-1.0f,1.0f,-1.0f,
-1.0f,1.0f,1.0f,
0,1.0f,0,
-1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,
//下面
0,-1.0f,0,
1.0f,-1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,-1.0f,0,
-1.0f,-1.0f,1.0f,
-1.0f,-1.0f,-1.0f,
0,-1.0f,0,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,-1.0f,0,
1.0f,-1.0f,-1.0f,
1.0f,-1.0f,1.0f
};
public Cube(Context context){
this.context = context;
vertexBuffer = ByteBuffer
.allocateDirect(vertices.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 把坐標們加入FloatBuffer中
vertexBuffer.put(vertices);
// 設置buffer,從第一個坐標開始讀
vertexBuffer.position(0);
}
}
我們每個面定義了12個頂點:
每一個面分為4個三角形,每個三角形包含3個點,共12個點(我們打算使用GL_TRIANGLES方式繪制 )
接下來看下我們的著色器代碼,頂點著色器我們使用仍然使用上一節的vertex_shader.glsl :
uniform mat4 u_Matrix;
attribute vec4 a_Position;
void main()
{
gl_Position = u_Matrix * a_Position;
}
u_Matrix用於我們傳入最終的變幻矩陣 (投影矩陣 and 攝像機矩陣)。
然後我們編譯鏈接著色器 此時Cube類代碼 (Cube.java ):
package com.cumt.shape;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.cumt.openglestwo_test_one.R;
import com.cumt.utils.ShaderHelper;
import com.cumt.utils.TextResourceReader;
import android.content.Context;
import android.opengl.GLES20;
public class Cube {
private FloatBuffer vertexBuffer;
private Context context;
//float類型的字節數
private static final int BYTES_PER_FLOAT = 4;
//共有72個頂點坐標,每個面包含12個頂點坐標
private static final int POSITION_COMPONENT_COUNT = 12*6;
// 數組中每個頂點的坐標數
private static final int COORDS_PER_VERTEX = 3;
private static final String A_POSITION = "a_Position";
private static final String U_COLOR = "u_Color";
private static final String U_MATRIX = "u_Matrix";
private int uMatrixLocation;
private int uColorLocation;
private int aPositionLocation;
private int program;
static float vertices[] = {
//前面
0,0,1.0f,
1.0f,1.0f,1.0f,
-1.0f,1.0f,1.0f,
0,0,1.0f,
-1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,0,1.0f,
-1.0f,-1.0f,1.0f,
1.0f,-1.0f,1.0f,
0,0,1.0f,
1.0f,-1.0f,1.0f,
1.0f,1.0f,1.0f,
//後面
0,0,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,0,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
0,0,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,0,-1.0f,
-1.0f,1.0f,-1.0f,
1.0f,1.0f,-1.0f,
//左面
-1.0f,0,0,
-1.0f,1.0f,1.0f,
-1.0f,1.0f,-1.0f,
-1.0f,0,0,
-1.0f,1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,0,0,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,1.0f,
-1.0f,0,0,
-1.0f,-1.0f,1.0f,
-1.0f,1.0f,1.0f,
//右面
1.0f,0,0,
1.0f,1.0f,1.0f,
1.0f,-1.0f,1.0f,
1.0f,0,0,
1.0f,-1.0f,1.0f,
1.0f,-1.0f,-1.0f,
1.0f,0,0,
1.0f,-1.0f,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,0,0,
1.0f,1.0f,-1.0f,
1.0f,1.0f,1.0f,
//上面
0,1.0f,0,
1.0f,1.0f,1.0f,
1.0f,1.0f,-1.0f,
0,1.0f,0,
1.0f,1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,1.0f,0,
-1.0f,1.0f,-1.0f,
-1.0f,1.0f,1.0f,
0,1.0f,0,
-1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,
//下面
0,-1.0f,0,
1.0f,-1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,-1.0f,0,
-1.0f,-1.0f,1.0f,
-1.0f,-1.0f,-1.0f,
0,-1.0f,0,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,-1.0f,0,
1.0f,-1.0f,-1.0f,
1.0f,-1.0f,1.0f
};
public Cube(Context context){
this.context = context;
vertexBuffer = ByteBuffer
.allocateDirect(vertices.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 把坐標們加入FloatBuffer中
vertexBuffer.put(vertices);
// 設置buffer,從第一個坐標開始讀
vertexBuffer.position(0);
getProgram();
uColorLocation = GLES20.glGetUniformLocation(program, U_COLOR);
aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
uMatrixLocation = GLES20.glGetUniformLocation(program, U_MATRIX);
//---------傳入頂點數據數據
GLES20.glVertexAttribPointer(aPositionLocation, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
}
//獲取program
private void getProgram(){
//獲取頂點著色器文本
String vertexShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.vertex_shader);
//獲取片段著色器文本
String fragmentShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.simple_fragment_shader);
//獲取program的id
program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource);
GLES20.glUseProgram(program);
}
}

package com.cumt.utils;
import android.opengl.Matrix;
//存儲系統矩陣狀態的類
public class MatrixState {
private static float[] mProjMatrix = new float[16];// 4x4矩陣 存儲投影矩陣
private static float[] mVMatrix = new float[16];// 攝像機位置朝向9參數矩陣
// 設置攝像機
public static void setCamera(float cx, // 攝像機位置x
float cy, // 攝像機位置y
float cz, // 攝像機位置z
float tx, // 攝像機目標點x
float ty, // 攝像機目標點y
float tz, // 攝像機目標點z
float upx, // 攝像機UP向量X分量
float upy, // 攝像機UP向量Y分量
float upz // 攝像機UP向量Z分量
) {
Matrix.setLookAtM(mVMatrix, 0, cx, cy, cz, tx, ty, tz, upx, upy, upz);
}
// 設置透視投影參數
public static void setProjectFrustum(float left, // near面的left
float right, // near面的right
float bottom, // near面的bottom
float top, // near面的top
float near, // near面距離
float far // far面距離
) {
Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);
}
// 獲取具體物體的總變換矩陣
static float[] mMVPMatrix = new float[16];
public static float[] getFinalMatrix() {
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
return mMVPMatrix;
}
}
package com.cumt.shape;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.cumt.openglestwo_test_one.R;
import com.cumt.utils.MatrixState;
import com.cumt.utils.ShaderHelper;
import com.cumt.utils.TextResourceReader;
import android.content.Context;
import android.opengl.GLES20;
public class Cube {
private FloatBuffer vertexBuffer;
private Context context;
//float類型的字節數
private static final int BYTES_PER_FLOAT = 4;
//共有72個頂點坐標,每個面包含12個頂點坐標
private static final int POSITION_COMPONENT_COUNT = 12*6;
// 數組中每個頂點的坐標數
private static final int COORDS_PER_VERTEX = 3;
private static final String A_POSITION = "a_Position";
private static final String U_COLOR = "u_Color";
private static final String U_MATRIX = "u_Matrix";
private int uMatrixLocation;
private int uColorLocation;
private int aPositionLocation;
private int program;
static float vertices[] = {
//前面
0,0,1.0f,
1.0f,1.0f,1.0f,
-1.0f,1.0f,1.0f,
0,0,1.0f,
-1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,0,1.0f,
-1.0f,-1.0f,1.0f,
1.0f,-1.0f,1.0f,
0,0,1.0f,
1.0f,-1.0f,1.0f,
1.0f,1.0f,1.0f,
//後面
0,0,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,0,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
0,0,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,0,-1.0f,
-1.0f,1.0f,-1.0f,
1.0f,1.0f,-1.0f,
//左面
-1.0f,0,0,
-1.0f,1.0f,1.0f,
-1.0f,1.0f,-1.0f,
-1.0f,0,0,
-1.0f,1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,0,0,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,1.0f,
-1.0f,0,0,
-1.0f,-1.0f,1.0f,
-1.0f,1.0f,1.0f,
//右面
1.0f,0,0,
1.0f,1.0f,1.0f,
1.0f,-1.0f,1.0f,
1.0f,0,0,
1.0f,-1.0f,1.0f,
1.0f,-1.0f,-1.0f,
1.0f,0,0,
1.0f,-1.0f,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,0,0,
1.0f,1.0f,-1.0f,
1.0f,1.0f,1.0f,
//上面
0,1.0f,0,
1.0f,1.0f,1.0f,
1.0f,1.0f,-1.0f,
0,1.0f,0,
1.0f,1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,1.0f,0,
-1.0f,1.0f,-1.0f,
-1.0f,1.0f,1.0f,
0,1.0f,0,
-1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,
//下面
0,-1.0f,0,
1.0f,-1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,-1.0f,0,
-1.0f,-1.0f,1.0f,
-1.0f,-1.0f,-1.0f,
0,-1.0f,0,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,-1.0f,0,
1.0f,-1.0f,-1.0f,
1.0f,-1.0f,1.0f
};
public Cube(Context context){
this.context = context;
vertexBuffer = ByteBuffer
.allocateDirect(vertices.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 把坐標們加入FloatBuffer中
vertexBuffer.put(vertices);
// 設置buffer,從第一個坐標開始讀
vertexBuffer.position(0);
getProgram();
uColorLocation = GLES20.glGetUniformLocation(program, U_COLOR);
aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
uMatrixLocation = GLES20.glGetUniformLocation(program, U_MATRIX);
//---------傳入頂點數據數據
GLES20.glVertexAttribPointer(aPositionLocation, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
}
//獲取program
private void getProgram(){
//獲取頂點著色器文本
String vertexShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.vertex_shader);
//獲取片段著色器文本
String fragmentShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.simple_fragment_shader);
//獲取program的id
program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource);
GLES20.glUseProgram(program);
}
public void draw(){
GLES20.glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 0.0f);
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, MatrixState.getFinalMatrix(),0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, POSITION_COMPONENT_COUNT);
}
}
package com.cumt.render;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import com.cumt.utils.MatrixState;
import com.cumt.shape.Cube;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glViewport;
public class MyRender implements Renderer {
private Context context;
public MyRender(Context context){
this.context = context;
}
// Circle circle;
Cube cube;
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.w("MyRender","onSurfaceCreated");
//設置屏幕背景色RGBA
glClearColor(0.5f,0.5f,0.5f, 1.0f);
// //打開深度檢測
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// //打開背面剪裁
GLES20.glEnable(GLES20.GL_CULL_FACE);
// circle = new Circle(context);
cube = new Cube(context);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
glViewport(0,0,width,height);
float ratio = (float) width / height;
//設置投影矩陣
// circle.projectionMatrix(width, height);
// 調用此方法計算產生透視投影矩陣
MatrixState.setProjectFrustum(-ratio,ratio, -1, 1, 20, 100);
// 調用此方法產生攝像機9參數位置矩陣
MatrixState.setCamera(-16f, 8f, 45, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
}
public void onDrawFrame(GL10 gl) {
// glClear(GL_COLOR_BUFFER_BIT);
//清除深度緩沖與顏色緩沖
glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
// circle.draw();
cube.draw();
}
}
然後我們回到MainActivity 設置屏幕顯示方式為豎屏,全屏 ,此時MainActivity代碼如下 (MainActivity.java):
package com.cumt.openglestwo_test_one;
import com.cumt.render.MyRender;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity {
private GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 設置為全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 設置為橫屏模式
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
glSurfaceView = new GLSurfaceView(this);
//OpenGL ES 2.0
glSurfaceView.setEGLContextClientVersion(2);
glSurfaceView.setRenderer(new MyRender(this));
// 設置渲染模式為主動渲染
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
setContentView(glSurfaceView);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
glSurfaceView.onPause();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
glSurfaceView.onResume();
}
}
在Cube類中定義頂點坐標,並轉化為FloatBuffer類型 ,此時代碼如下 (Cube.java ) :
package com.cumt.shape;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.cumt.openglestwo_test_one.R;
import com.cumt.utils.MatrixState;
import com.cumt.utils.ShaderHelper;
import com.cumt.utils.TextResourceReader;
import android.content.Context;
import android.opengl.GLES20;
public class Cube {
//頂點坐標
private FloatBuffer vertexBuffer;
//顏色坐標
private FloatBuffer colorBuffer;
private Context context;
//float類型的字節數
private static final int BYTES_PER_FLOAT = 4;
//共有72個頂點坐標,每個面包含12個頂點坐標
private static final int POSITION_COMPONENT_COUNT = 12*6;
// 數組中每個頂點的坐標數
private static final int COORDS_PER_VERTEX = 3;
private static final String A_POSITION = "a_Position";
private static final String U_COLOR = "u_Color";
private static final String U_MATRIX = "u_Matrix";
private int uMatrixLocation;
private int uColorLocation;
private int aPositionLocation;
private int program;
static float vertices[] = {
//前面
0,0,1.0f,
1.0f,1.0f,1.0f,
-1.0f,1.0f,1.0f,
0,0,1.0f,
-1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,0,1.0f,
-1.0f,-1.0f,1.0f,
1.0f,-1.0f,1.0f,
0,0,1.0f,
1.0f,-1.0f,1.0f,
1.0f,1.0f,1.0f,
//後面
0,0,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,0,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
0,0,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,0,-1.0f,
-1.0f,1.0f,-1.0f,
1.0f,1.0f,-1.0f,
//左面
-1.0f,0,0,
-1.0f,1.0f,1.0f,
-1.0f,1.0f,-1.0f,
-1.0f,0,0,
-1.0f,1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,0,0,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,1.0f,
-1.0f,0,0,
-1.0f,-1.0f,1.0f,
-1.0f,1.0f,1.0f,
//右面
1.0f,0,0,
1.0f,1.0f,1.0f,
1.0f,-1.0f,1.0f,
1.0f,0,0,
1.0f,-1.0f,1.0f,
1.0f,-1.0f,-1.0f,
1.0f,0,0,
1.0f,-1.0f,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,0,0,
1.0f,1.0f,-1.0f,
1.0f,1.0f,1.0f,
//上面
0,1.0f,0,
1.0f,1.0f,1.0f,
1.0f,1.0f,-1.0f,
0,1.0f,0,
1.0f,1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,1.0f,0,
-1.0f,1.0f,-1.0f,
-1.0f,1.0f,1.0f,
0,1.0f,0,
-1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,
//下面
0,-1.0f,0,
1.0f,-1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,-1.0f,0,
-1.0f,-1.0f,1.0f,
-1.0f,-1.0f,-1.0f,
0,-1.0f,0,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,-1.0f,0,
1.0f,-1.0f,-1.0f,
1.0f,-1.0f,1.0f
};
//頂點顏色值數組,每個頂點4個色彩值RGBA
static float colors[]=new float[]{
//前面
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
//後面
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
//左面
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
//右面
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
//上面
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
//下面
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
};
public Cube(Context context){
this.context = context;
vertexBuffer = ByteBuffer
.allocateDirect(vertices.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 把坐標們加入FloatBuffer中
vertexBuffer.put(vertices);
// 設置buffer,從第一個坐標開始讀
vertexBuffer.position(0);
//顏色buffer
colorBuffer = ByteBuffer
.allocateDirect(colors.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
getProgram();
uColorLocation = GLES20.glGetUniformLocation(program, U_COLOR);
aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
uMatrixLocation = GLES20.glGetUniformLocation(program, U_MATRIX);
//---------傳入頂點數據數據
GLES20.glVertexAttribPointer(aPositionLocation, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
}
//獲取program
private void getProgram(){
//獲取頂點著色器文本
String vertexShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.vertex_shader);
//獲取片段著色器文本
String fragmentShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.simple_fragment_shader);
//獲取program的id
program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource);
GLES20.glUseProgram(program);
}
public void draw(){
GLES20.glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 0.0f);
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, MatrixState.getFinalMatrix(),0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, POSITION_COMPONENT_COUNT);
}
}
//vertex_shader_cube.glsl
uniform mat4 u_Matrix;
attribute vec4 a_Position;
attribute vec4 a_Color; //頂點顏色
varying vec4 v_Color; //用於傳遞給片元著色器的變量
void main()
{
gl_Position = u_Matrix * a_Position;
v_Color = a_Color;//將接收的顏色傳遞給片元著色器
}
//fragment_shader_cube.glsl
precision mediump float;
varying vec4 v_Color; //接收從頂點著色器過來的參數
void main()
{
gl_FragColor = v_Color;
}
去點原來的引入顏色的相關代碼,加入當前要傳遞的顏色相關的代碼,此時Cube類如下 (Cube.java ) :
package com.cumt.shape;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.cumt.openglestwo_test_one.R;
import com.cumt.utils.MatrixState;
import com.cumt.utils.ShaderHelper;
import com.cumt.utils.TextResourceReader;
import android.content.Context;
import android.opengl.GLES20;
public class Cube {
//頂點坐標
private FloatBuffer vertexBuffer;
//顏色坐標
private FloatBuffer colorBuffer;
private Context context;
//float類型的字節數
private static final int BYTES_PER_FLOAT = 4;
//共有72個頂點坐標,每個面包含12個頂點坐標
private static final int POSITION_COMPONENT_COUNT = 12*6;
// 數組中每個頂點的坐標數
private static final int COORDS_PER_VERTEX = 3;
// 顏色數組中每個顏色的值數
private static final int COORDS_PER_COLOR = 4;
private static final String A_POSITION = "a_Position";
private static final String A_COLOR = "a_Color";
private static final String U_MATRIX = "u_Matrix";
private int uMatrixLocation;
private int aColorLocation;
private int aPositionLocation;
private int program;
static float vertices[] = {
//前面
0,0,1.0f,
1.0f,1.0f,1.0f,
-1.0f,1.0f,1.0f,
0,0,1.0f,
-1.0f,1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,0,1.0f,
-1.0f,-1.0f,1.0f,
1.0f,-1.0f,1.0f,
0,0,1.0f,
1.0f,-1.0f,1.0f,
1.0f,1.0f,1.0f,
//後面
0,0,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,0,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
0,0,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,0,-1.0f,
-1.0f,1.0f,-1.0f,
1.0f,1.0f,-1.0f,
//左面
-1.0f,0,0,
-1.0f,1.0f,1.0f,
-1.0f,1.0f,-1.0f,
-1.0f,0,0,
-1.0f,1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,0,0,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,1.0f,
-1.0f,0,0,
-1.0f,-1.0f,1.0f,
-1.0f,1.0f,1.0f,
//右面
1.0f,0,0,
1.0f,1.0f,1.0f,
1.0f,-1.0f,1.0f,
1.0f,0,0,
1.0f,-1.0f,1.0f,
1.0f,-1.0f,-1.0f,
1.0f,0,0,
1.0f,-1.0f,-1.0f,
1.0f,1.0f,-1.0f,
1.0f,0,0,
1.0f,1.0f,-1.0f,
1.0f,1.0f,1.0f,
//上面
0,1.0f,0,
1.0f,1.0f,1.0f,
1.0f,1.0f,-1.0f,
0,1.0f,0,
1.0f,1.0f,-1.0f,
-1.0f,1.0f,-1.0f,
0,1.0f,0,
-1.0f,1.0f,-1.0f,
-1.0f,1.0f,1.0f,
0,1.0f,0,
-1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,
//下面
0,-1.0f,0,
1.0f,-1.0f,1.0f,
-1.0f,-1.0f,1.0f,
0,-1.0f,0,
-1.0f,-1.0f,1.0f,
-1.0f,-1.0f,-1.0f,
0,-1.0f,0,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
0,-1.0f,0,
1.0f,-1.0f,-1.0f,
1.0f,-1.0f,1.0f
};
//頂點顏色值數組,每個頂點4個色彩值RGBA
static float colors[]=new float[]{
//前面
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
1,1,1,0,//中間為白色
1,0,0,0,
1,0,0,0,
//後面
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
1,1,1,0,//中間為白色
0,0,1,0,
0,0,1,0,
//左面
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
1,1,1,0,//中間為白色
1,0,1,0,
1,0,1,0,
//右面
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
1,1,1,0,//中間為白色
1,1,0,0,
1,1,0,0,
//上面
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
1,1,1,0,//中間為白色
0,1,0,0,
0,1,0,0,
//下面
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
1,1,1,0,//中間為白色
0,1,1,0,
0,1,1,0,
};
public Cube(Context context){
this.context = context;
vertexBuffer = ByteBuffer
.allocateDirect(vertices.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 把坐標們加入FloatBuffer中
vertexBuffer.put(vertices);
// 設置buffer,從第一個坐標開始讀
vertexBuffer.position(0);
//顏色buffer
colorBuffer = ByteBuffer
.allocateDirect(colors.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
getProgram();
aColorLocation = GLES20.glGetAttribLocation(program, A_COLOR);
aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
uMatrixLocation = GLES20.glGetUniformLocation(program, U_MATRIX);
//---------傳入頂點數據數據
GLES20.glVertexAttribPointer(aPositionLocation, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
//---------傳入顏色數據
GLES20.glVertexAttribPointer(aColorLocation, COORDS_PER_COLOR,
GLES20.GL_FLOAT, false, 0, colorBuffer);
GLES20.glEnableVertexAttribArray(aColorLocation);
}
//獲取program
private void getProgram(){
//獲取頂點著色器文本
String vertexShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.vertex_shader_cube);
//獲取片段著色器文本
String fragmentShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.fragment_shader_cube);
//獲取program的id
program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource);
GLES20.glUseProgram(program);
}
public void draw(){
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, MatrixState.getFinalMatrix(),0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, POSITION_COMPONENT_COUNT);
}
}
運行一下看看結果 :
哈 現在我們的立方體就完成了 ,是不是很漂亮 。 關於顏色設置,這裡用到了OpenglEs 的平滑著色 ,如果有不明白的
可以去按照 “opengl es 平滑著色 ” 這個關鍵字搜索一下 。這裡不再講解。
詳解Android 進程間通信的幾種實現方式
一、概述由於應用程序之間不能共享內存。在不同應用程序之間交互數據(跨進程通訊),在Android SDK中提供了4種用於跨進程通訊的方式。這4種方式正好對應於androi
Android 編程下的計時器代碼
同樣,為了防止用戶惡意的頻繁發送激活碼,應用中需要對用戶發送激活碼的時間間隔進行限制,這時就需要用到倒計時器了,大概流程是這樣的:頁面初始化的時候,按鈕為可點擊狀態,用戶
小豬的Android入門之路 Day 8 part 2
本節引言: 在part 1中我們學習了網絡交互中用得較多的xml文件的相關概念,以及在Android中常用的 解析XML三種不同形式,分別SA
Android Studio如何使用Git提交代碼到GitHub和OsChina並解決沖突
由於本人喜愛Git,那就介紹Git,,如何和在GitHub和Oschina拉取和提交項目,並且你會學會如何解決沖突問題!!博主還是那個圖片控!!准備工作git下載地址:G