1.本系列借花獻佛,結合了不少前人的文章以及書籍,我儘量去總結並用個人思想進行加工
2.OpenGL一直是個人心結,也是時候去解開了,本系列稱不上原創,但每行代碼都有着我思考的痕跡
3.本系列全部的圖片都是[張風捷特烈]所畫,若是有什麼錯誤還請指出,定會最快改正
4.本系列文章容許轉載、截取、公衆號發佈,請保留前言部分,但願廣大讀者悉心指教
html
傳說,在這片代碼大陸上,存在一個古老的種族,它們擁有無盡的力量,卻罕有人可以駕馭
多媒體王國中存在一個隱蔽的角落,是這個種族的棲息之地,不多有人敢冒犯那裏
Android多媒體領域有一處:被後人稱爲黑龍洞穴--OpenGL ES
,其中埋藏着圖形界的無限財富
勇士們,舉起手中的劍,進發!java
黑龍洞口
NPC:黑龍洞口一片漆黑,其中隱藏着什麼規律,勇士們,一塊兒尋找吧!git
GLSurfaceView的使用
/**
* 做者:張風捷特烈<br/>
* 時間:2019/1/9 0009:18:25<br/>
* 郵箱:1981462002@qq.com<br/>
* 說明:GL測試視圖
*/
public class GLView extends GLSurfaceView {
private GLRenderer mRenderer;
public GLView(Context context) {
this(context,null);
}
public GLView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setEGLContextClientVersion(2);//設置OpenGL ES 2.0 context
mRenderer = new GLRenderer();
setRenderer(mRenderer);//設置渲染器
}
}
複製代碼
LSurfaceView.Renderer
的使用/**
* 做者:張風捷特烈<br/>
* 時間:2019/1/9 0009:18:56<br/>
* 郵箱:1981462002@qq.com<br/>
* 說明:GL渲染類
*/
public class GLRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);//rgba
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);//GL視口
}
@Override
public void onDrawFrame(GL10 gl) {
//清除顏色緩存和深度緩存
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
}
}
複製代碼
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GLView(this));
}
}
複製代碼
/**
* 做者:張風捷特烈<br/>
* 時間:2019/1/9 0009:20:09<br/>
* 郵箱:1981462002@qq.com<br/>
* 說明:三角形
*/
public class Triangle {
private FloatBuffer vertexBuffer;//頂點緩衝
private final String vertexShaderCode =//頂點着色代碼
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =//片元着色代碼
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private final int mProgram;
private int mPositionHandle;//位置句柄
private int mColorHandle;//顏色句柄
private final int vertexCount = sCoo.length / COORDS_PER_VERTEX;//頂點個數
private final int vertexStride = COORDS_PER_VERTEX * 4; // 3*4=12
// 數組中每一個頂點的座標數
static final int COORDS_PER_VERTEX = 3;
static float sCoo[] = { //以逆時針順序
0.0f, 0.0f, 0.0f, // 頂部
-1.0f, -1.0f, 0.0f, // 左下
1.0f, -1.0f, 0.0f // 右下
};
// 顏色,rgba
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};
public Triangle() {
//初始化頂點字節緩衝區
ByteBuffer bb = ByteBuffer.allocateDirect(sCoo.length * 4);//每一個浮點數:座標個數* 4字節
bb.order(ByteOrder.nativeOrder());//使用本機硬件設備的字節順序
vertexBuffer = bb.asFloatBuffer();// 從字節緩衝區建立浮點緩衝區
vertexBuffer.put(sCoo);// 將座標添加到FloatBuffer
vertexBuffer.position(0);//設置緩衝區以讀取第一個座標
int vertexShader = GLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,//頂點着色
vertexShaderCode);
int fragmentShader = GLRenderer.loadShader
(GLES20.GL_FRAGMENT_SHADER,//片元着色
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();//建立空的OpenGL ES 程序
GLES20.glAttachShader(mProgram, vertexShader);//加入頂點着色器
GLES20.glAttachShader(mProgram, fragmentShader);//加入片元着色器
GLES20.glLinkProgram(mProgram);//建立可執行的OpenGL ES項目
}
public void draw() {
// 將程序添加到OpenGL ES環境中
GLES20.glUseProgram(mProgram);
//獲取頂點着色器的vPosition成員的句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//啓用三角形頂點的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//準備三角座標數據
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// 獲取片元着色器的vColor成員的句柄
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
//爲三角形設置顏色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//繪製三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁用頂點數組
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
複製代碼
/**
* 做者:張風捷特烈<br/>
* 時間:2019/1/9 0009:18:56<br/>
* 郵箱:1981462002@qq.com<br/>
* 說明:GL渲染類
*/
public class GLRenderer implements GLSurfaceView.Renderer {
Triangle mTriangle;
/**
* 加載做色器
* @param type 頂點着色 {@link GLES20.GL_VERTEX_SHADER}
* 片元着色 {@link GLES20.GL_FRAGMENT_SHADER}
* @param shaderCode 着色代碼
* @return 做色器
*/
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);//建立着色器
GLES20.glShaderSource(shader, shaderCode);//添加着色器源代碼
GLES20.glCompileShader(shader);//編譯
return shader;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);//rgba
mTriangle = new Triangle();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);//GL視口
}
@Override
public void onDrawFrame(GL10 gl) {
//清除顏色緩存和深度緩存
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
mTriangle.draw();
}
}
複製代碼
NPC:勇者,你陣亡了沒...若是如今退出還來得及,這將是一篇宏偉的戰鬥史詩
若是你還想繼續,舉起你手中的劍,同我一塊兒,進發!!!github
/**
* 加載做色器
* @param type 頂點着色 {@link GLES20.GL_VERTEX_SHADER}
* 片元着色 {@link GLES20.GL_FRAGMENT_SHADER}
* @param shaderCode 着色代碼
* @return 做色器
*/
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);//建立着色器
GLES20.glShaderSource(shader, shaderCode);//添加着色器源代碼
GLES20.glCompileShader(shader);//編譯
return shader;
}
複製代碼
private final String vertexShaderCode =//頂點着色代碼
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =//片元着色代碼
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
int vertexShader = GLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,//頂點着色
vertexShaderCode);
int fragmentShader = GLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,//片元着色
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();//建立空的OpenGL ES 程序
GLES20.glAttachShader(mProgram, vertexShader);//加入頂點着色器
GLES20.glAttachShader(mProgram, fragmentShader);//加入片元着色器
GLES20.glLinkProgram(mProgram);//建立可執行的OpenGL ES項目
複製代碼
private FloatBuffer vertexBuffer;//頂點緩衝
private final int vertexCount = sCoo.length / COORDS_PER_VERTEX;//頂點個數
private final int vertexStride = COORDS_PER_VERTEX * 4; // 3*4=12
static final int COORDS_PER_VERTEX = 3;//數組中每一個頂點的座標數
static float sCoo[] = { //以逆時針順序
0.0f, 0.0f, 0.0f, // 頂部
-1.0f, -1.0f, 0.0f, // 左下
1.0f, -1.0f, 0.0f // 右下
};
//初始化頂點字節緩衝區
ByteBuffer bb = ByteBuffer.allocateDirect(sCoo.length * 4);//每一個浮點數:座標個數* 4字節
bb.order(ByteOrder.nativeOrder());//使用本機硬件設備的字節順序
vertexBuffer = bb.asFloatBuffer();// 從字節緩衝區建立浮點緩衝區
vertexBuffer.put(sCoo);// 將座標添加到FloatBuffer
vertexBuffer.position(0);//設置緩衝區以讀取第一個座標
複製代碼
public void draw() {
// 將程序添加到OpenGL ES環境中
GLES20.glUseProgram(mProgram);
//獲取頂點着色器的vPosition成員的句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//啓用三角形頂點的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//準備三角座標數據
GLES20.glVertexAttribPointer(
mPositionHandle,//int indx, 索引
COORDS_PER_VERTEX,//int size,大小
GLES20.GL_FLOAT,//int type,類型
false,//boolean normalized,//是否標準化
vertexStride,// int stride,//跨度
vertexBuffer);// java.nio.Buffer ptr//緩衝
// 獲取片元着色器的vColor成員的句柄
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
//爲三角形設置顏色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//繪製三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁用頂點數組:
//禁用index指定的通用頂點屬性數組。
// 默認狀況下,禁用全部客戶端功能,包括全部通用頂點屬性數組。
// 若是啓用,將訪問通用頂點屬性數組中的值,
// 並在調用頂點數組命令(如glDrawArrays或glDrawElements)時用於呈現
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
複製代碼
龍之怒色
GLSL(OpenGL Shader Language)數組
1.一種面相過程的高級語言
2.基於C/C++的語法(子集)及流程控制
3.完美支持向量和矩陣的操做
4.經過類型限定符來管理輸入與輸出
複製代碼
沒有統一的拓展名,通過百度,感受這種方式比較符合個人審美
並且AndroidStudio支持這些拓展名,你都叫.glsl
也能夠,能分清就像緩存
.vert - 頂點着色器
.tesc - 曲面細分控制着色器
.tese - 曲面細分評估着色器
.geom - 幾何着色器
.frag - 片元着色器
.comp - 計算着色器
複製代碼
標量:一維的數值操做bash
float 浮點型
bool 布爾型
int 整型
|--- 支持 8進制(0開頭) 16進制(0x開頭)
複製代碼
向量:儲存及操做 顏色、位置、紋理座標等微信
vec2 二維向量型-浮點型
vec3 三維向量型-浮點型
vec4 四維向量型-浮點型
ivec2 二維向量型-整型
ivec3 三維向量型-整型
ivec4 四維向量型-整型
bvec2 二維向量型-布爾型
bvec3 三維向量型-布爾型
bvec4 四維向量型-布爾型
複製代碼
矩陣:根據矩陣的運算進行變換操做app
mat2 2X2矩陣-浮點型
mat3 3X3矩陣-浮點型
mat4 4X4矩陣-浮點型
複製代碼
採樣器ide
sampler2D 二維紋理
sampler3D 三維紋理
samplerCube 立方貼圖紋理
複製代碼
結構體:例如
struct ball{
vec3 color;
vec3 position;
}
複製代碼
數組
vec3 pos[]; //聲明不定大小的三維向量數組
vec3 pos[6];//聲明6個三維向量數組
複製代碼
attribute 頂點的變量,如頂點位置,顏色
uniform
varying 用於從定點着色器傳遞到片元做色器的變量
const
precision 精度
|---lowp
|---mediump
|---highp
複製代碼
加載着色腳本的代碼差很少,封裝一下,寫個GLUtils吧:
/**
* 做者:張風捷特烈<br/>
* 時間:2019/1/10 0010:10:58<br/>
* 郵箱:1981462002@qq.com<br/>
* 說明:OpenGL ES 輔助工具
*/
public class GLUtils {
//從腳本中加載shader內容的方法
public static int loadShaderAssets(Context ctx, int type, String name) {
String result = null;
try {
InputStream in = ctx.getAssets().open(name);
int ch = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((ch = in.read()) != -1) {
baos.write(ch);
}
byte[] buff = baos.toByteArray();
baos.close();
in.close();
result = new String(buff, "UTF-8");
result = result.replaceAll("\\r\\n", "\n");
} catch (Exception e) {
e.printStackTrace();
}
return loadShader(type, result);
}
/**
* 加載做色器
*
* @param type 着色器類型 頂點着色 {@link GLES20.GL_VERTEX_SHADER}
* 片元着色 {@link GLES20.GL_FRAGMENT_SHADER}
* @param shaderCode 着色代碼
* @return 做色器
*/
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);//建立着色器
if (shader == 0) {//加載失敗直接返回
return 0;
}
GLES20.glShaderSource(shader, shaderCode);//加載着色器源代碼
GLES20.glCompileShader(shader);//編譯
return checkCompile(type, shader);
}
/**
* 檢查shader代碼是否編譯成功
*
* @param type 着色器類型
* @param shader 着色器
* @return 着色器
*/
private static int checkCompile(int type, int shader) {
int[] compiled = new int[1];//存放編譯成功shader數量的數組
//獲取Shader的編譯狀況
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {//若編譯失敗則顯示錯誤日誌並
Log.e("ES20_COMPILE_ERROR",
"Could not compile shader " + type + ":" + GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);//刪除此shader
shader = 0;
}
return shader;
}
}
複製代碼
tri.frag
和tri.vert
的分析tri.frag
第一句是聲明片元的精度
第二句是聲明片元的顏色:一個vec4的變量--vColor
gl_FragColor = vColor;
gl_FragColor是gl內定名,將vColor值賦給它
precision mediump float;
uniform vec4 vColor;
void main() {
gl_FragColor = vColor;
}
複製代碼
單看一下着色的操做流程:
因此從Java代碼來看,重點在color,它是一個四值數組,每一個值0~1
分別對應r,g,b,a
四值,即紅,綠,藍,透明
四個顏色維度
// 顏色,rgba
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};
複製代碼
更換顏色:
rgba 132,197,240,255---->0.5176471f, 0.77254903f, 0.9411765f, 1.0f
定義了一個四維的向量給gl_Position
attribute vec4 vPosition;
void main() {
gl_Position = vPosition;
}
複製代碼
關於頂點的緩衝 初始化階段將頂點數據通過基本處理
static float sCoo[] = { //以逆時針順序
0.0f, 0.0f, 0.0f, // 頂部
-1.0f, -1.0f, 0.0f, // 左下
1.0f, -1.0f, 0.0f // 右下
};
/**
* 緩衝數據
*/
private void bufferData() {
ByteBuffer bb = ByteBuffer.allocateDirect(sCoo.length * 4);//每一個浮點數:座標個數* 4字節
bb.order(ByteOrder.nativeOrder());//使用本機硬件設備的字節順序
vertexBuffer = bb.asFloatBuffer();// 從字節緩衝區建立浮點緩衝區
vertexBuffer.put(sCoo);// 將座標添加到FloatBuffer
vertexBuffer.position(0);//設置緩衝區以讀取第一個座標
}
複製代碼
每三個數是一個頂點,分別表明(x,y,z),先卡z=0,也就是二維座標系
通過三個點的測試,能夠發現是一箇中心在原點,左右跨度爲1的座標系
變更座標
頂點着色
剛纔是給片元進行着色的,如今看看怎麼給頂點着色,確定要有頂點變量
前面關於修飾關鍵字:varying 用於從定點着色器傳遞到片元做色器的變量
tri.vert
attribute vec3 vPosition;//頂點座標
uniform mat4 uMVPMatrix; //總變換矩陣
attribute vec4 aColor;//頂點顏色
varying vec4 vColor;//片元顏色
void main() {
gl_Position = uMVPMatrix*vec4(vPosition,1);
vColor = aColor;//將頂點顏色傳給片元
}
複製代碼
tri.frag
precision mediump float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}
複製代碼
Triangle.java
三個點,第三個顏色,頂點+緩衝,跟頂點座標一個套路,取
黃、藍、綠
三色
//成員變量
private FloatBuffer mColorBuffer;//顏色緩衝
static final int COLOR_PER_VERTEX = 4;//向量維度
private final int vertexColorStride = COLOR_PER_VERTEX * 4; // 4*4=16
float colors[] = new float[]{
1f, 1f, 0.0f, 1.0f,//黃
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//藍
0.19607843f, 1.0f, 0.02745098f, 1.0f//綠
};
//注意顏色句柄不是uniform了,獲取片元着色器的vColor成員的句柄
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
//啓用三角形頂點顏色的句柄
GLES20.glEnableVertexAttribArray(mColorHandle);
//準備三角頂點顏色數據
GLES20.glVertexAttribPointer(
mColorHandle,
COLOR_PER_VERTEX,
GLES20.GL_FLOAT,
false,
vertexColorStride,
mColorBuffer);
複製代碼
龍之赤瞳
先看這個圖,按這樣來畫我的臉,豈不是會扁掉?這怎麼能忍
Matrix.setLookAtM
一共11個參數,嚇得我一抖,通過百度,再加上我
神級的Ps技能
,繪圖以下
主要有三個點eye(相機/眼睛位置),center(觀察物的位置),up(擡頭的感受,意會一下...)
public static void setLookAtM(float[] rm, int rmOffset,
float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ,
float upX, float upY,float upZ) {
複製代碼
Matrix.frustumM
八個參數,還好還好,也不是太多...
Matrix.frustumM(float[] m, int offset,
float left, float right, float bottom, float top,
float near, float far)
複製代碼
//Model View Projection Matrix--模型視圖投影矩陣
private final float[] mMVPMatrix = new float[16];
//投影矩陣 mProjectionMatrix
private final float[] mProjectionMatrix = new float[16];
//視圖矩陣 mViewMatrix
private final float[] mViewMatrix = new float[16];
---->[GLRenderer#onSurfaceChanged]-------
float ratio = (float) width / height;
//透視投影矩陣--截錐
Matrix.frustumM(mProjectionMatrix, 0,
-ratio, ratio, -1, 1,
3, 7);
// 設置相機位置(視圖矩陣)
Matrix.setLookAtM(mViewMatrix, 0,
0, 0, -3,
0f, 0f, 0f,
0f, 1.0f, 0.0f);
---->[GLRenderer#onDrawFrame]-------
// 計算投影和視圖轉換
Matrix.multiplyMM(
mMVPMatrix, 0,
mProjectionMatrix, 0,
mViewMatrix, 0);
mTriangle.draw(mMVPMatrix);
複製代碼
tri.vert
:爲頂點添加矩陣變換attribute vec3 vPosition;//頂點座標
uniform mat4 uMVPMatrix; //總變換矩陣
void main() {
gl_Position = uMVPMatrix*vec4(vPosition,1);
}
複製代碼
Triangle.java
//獲取程序中總變換矩陣uMVPMatrix成員的句柄
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
---->[Triangle#draw]-------------
//對頂點進行矩陣變換
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpMatrix, 0);
複製代碼
龍之振翼
對
mMVPMatrix
再進行矩陣變換就好了
//變換矩陣
private float[] mOpMatrix = new float[16];
---->[GLRenderer#onDrawFrame]-------
//mOpMatrix旋轉變換
Matrix.setRotateM(mOpMatrix, 0, 30, 0, 0, -1);
//使用mOpMatrix對mMVPMatrix進行變換
Matrix.multiplyMM(
mMVPMatrix, 0,
mViewMatrix, 0,
mOpMatrix, 0);
Matrix.multiplyMM(
mMVPMatrix, 0,
mProjectionMatrix, 0,
mMVPMatrix, 0);
複製代碼
Matrix.multiplyMM
我知道你看得一臉懵X,如今看看multiplyMM是個什麼東西
怎麼看?固然先看源碼啦,這是目前OpenGl ES 裏我見過註釋最多的...
將兩個4x4矩陣相乘,並將結果存儲在第三個4x4矩陣中。其中:result = lhs x rhs。
因爲矩陣相乘的工做方式,結果矩陣的效果至關於先被右邊的矩陣乘,再被左邊的矩陣乘。
這跟你指望的狀況是相反的。
result 保存結果的浮點數組
lhs 保存左側矩陣的浮點數組。
rhs 保存右側矩陣的浮點數組。
三個對應的offset--偏移量
public static native void multiplyMM(float[] result, int resultOffset,
float[] lhs, int lhsOffset, float[] rhs, int rhsOffset);
複製代碼
這裏都是用16個float的數組成的矩陣,寫個方法打印出來再說
public static void logM(float[] matrix) {
logM(matrix, "Matrix");
}
/**
* 打印方陣數組
*
* @param matrix
* @param name
*/
public static void logM(float[] matrix, String name) {
int wei = (int) Math.sqrt(matrix.length);
StringBuffer sb = new StringBuffer("\n[");
for (int i = 0; i < matrix.length; i++) {
sb.append(matrix[i]);
if ((i + 1) % wei == 0) {
if (i == matrix.length - 1) {
sb.append("]");
continue;
}
sb.append("\n");
continue;
}
sb.append(" , ");
}
Log.e("Matrix_TAG", name + ": " + sb.toString());
}
複製代碼
如今回頭再來看看:
mOpMatrix原本全是0,通過setRotateM以後變成圖中第一個矩陣
第一個Matrix.multiplyMM
將mOpMatrix
矩陣做用於mViewMatrix
上,得到結果矩陣:mMVPMatrix
第二個Matrix.multiplyMM
將mMVPMatrix
矩陣做用於mProjectionMatrix
上,得到結果矩陣:mMVPMatrix
最後根據頂點變換矩陣的句柄,將mMVPMatrix在tri.vert中做用在頂點上
//變換矩陣
private float[] mOpMatrix = new float[16];
//mOpMatrix旋轉變換
Matrix.setRotateM(mOpMatrix, 0, 30, 0, 0, -1);
//使用mOpMatrix對mMVPMatrix進行變換
Matrix.multiplyMM(
mMVPMatrix, 0,
mViewMatrix, 0,
mOpMatrix, 0);
Matrix.multiplyMM(
mMVPMatrix, 0,
mProjectionMatrix, 0,
mMVPMatrix, 0);
複製代碼
當GLSurfaceView的
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY)
;時
Renderer
的onDrawFrame(GL10 gl) {
會不斷執行,更新的時間間隔和手機有關
個人真機在13~19ms
之間,模擬器在16~48ms
之間,看了一下,轉一圈用6s,
即6000ms,一共360°,每次+1°,使用平均每度(每次刷新)用了16.667ms,好吧,完美的60fps
private int currDeg = 0;
---->[GLRenderer#onDrawFrame]-------
//初始化變換矩陣
Matrix.setRotateM(mOpMatrix, 0, currDeg, 0, 0, -1);
Matrix.multiplyMM(mMVPMatrix, 0,
mViewMatrix, 0,
mOpMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0,
mProjectionMatrix, 0,
mMVPMatrix, 0);
mTriangle.draw(mMVPMatrix);
currDeg++;
if (currDeg == 360) {
currDeg = 0;
}
複製代碼
你拍照的時候怎麼讓成像縮小?----日後退唄!
根據後退爲正,能夠推測出座標系是一個右手系,也就是z軸朝向咱們
執行很簡單:Matrix.translateM
就能夠將mOpMatrix進行平移操做
以咱們的視角(參考系):你能夠想象成圖形(觀察物)一邊旋轉一邊原離咱們,也能夠反過來想一想
引擎推進的不是飛船而是宇宙。飛船壓根就沒動過。
--若是對矩陣有興趣,建議把這篇看十遍
//設置沿Z軸位移
Matrix.translateM(mOpMatrix, 0, 0, 0, currDeg/90.f);
複製代碼
NPC: 恭喜您,完成第四副本,如今您得到OpenGL-ES 新手戰士的稱號,請留下名號:
我(輸入):張風捷特烈
NPC: 張風捷特烈,是否繼續前行,下面的關卡將更加艱難
我:(點擊肯定) 執劍向前
NPC: 尊敬的勇者-張風捷特烈,祝您一路平安,成功斬殺黑龍...
第一集結束,下一集:"謎團立方" 敬請期待
項目源碼 | 日期 | 備註 |
---|---|---|
V0.1-github | 2018-1-11 | Android多媒體之GL-ES戰記第一集--勇者集結 |
筆名 | 微信 | 愛好 | |
---|---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 | 語言 |
個人github | 個人簡書 | 個人掘金 | 我的網站 |
本文參考:
1.《Android 3D遊戲開發技術寶典 OpenGL ES 2.0》
2.OpenGL ES 學習記錄
3.opengl-tutorial:OpenGL基礎知識
4.廣大網友的文章零散參考,就不一一列舉了