opengl es3.0遊戲開發學習筆記1-繪製旋轉的三角形
前段時間一直在看opengl es2.0遊戲開發的知識 ,這幾天買了本opengl es3.0遊戲開發的書
打算一邊學習一邊整理學習筆記,我的開發環境是Android studio 2.1.3,不過有個問題是Android studio自帶的模擬器只能支援es2.0
無法使用es3.0 所以3.0只能在真機上除錯,手機必須是4.3或者是以上系統,我試過4.3的三星s3和 6.0的華為mates。下面是效果圖
首先是各個類的功能
LoggerConfig這個類是控制錯誤日誌輸出的,這個其實很簡單裡面就一句話,在錯誤日誌輸出時判斷它裡面是不是true
MyActivity這個類是主活動的類,建立了檢視,在這裡把顯示的檢視設定為opengl的視視窗。
MyTDView這個類是繼承自GLSurfaceView 實現opengl的視窗和 一個渲染器,我是這麼理解的
shaderUtil是著色器的幫助類 實現讀取著色器和編譯連線
Tringle是繪製三角形
我個人感覺整體過過程是這樣的
下邊是LoggerConfig的程式碼
package com.opengl.a3_1_triangle; /** * Created by admin on 2016/11/12. */ public class LoggerConfig { public static final boolean ON = true; //在後面輸出錯誤日誌時判斷是不是true
}
下邊是從shaderUtil幫助類的程式碼
首先得實現的是把著色器程式碼從文字中讀取出來並且進行編譯,書中作者使用的是把著色器程式碼寫在sh指令碼中然後讀取,Android studio中有glsl著色器的外掛,安裝後可以使用glsl格式文字,glsl格式額能提示關鍵字有個好處是防止著色器程式寫錯。
程式碼
package com.opengl.a3_1_triangle; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.opengl.GLES20; import android.opengl.GLES30; import android.util.Log; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * Created by admin on 2016/11/12. */ //載入頂點shader與片元shader的工具類 public class ShaderUtil { //載入定製shader的方法 public static int loadShader( int shaderType,//shader的型別 GLES30.GL_VERTEX_SHADER(頂點) GLES30.GL_FRAGMENT_SHADER(片元) String source //shader的指令碼字串 ){ //建立一個新的Shader int shader = GLES30.glCreateShader(shaderType); //建立成功則載入shader if(shader!=0) { //載入shader的原始碼 GLES30.glShaderSource(shader,source); //編譯shader GLES30.glCompileShader(shader); //存放編譯成功shader數量的陣列 int [] compile=new int[1]; //獲取Shader的編譯情況 GLES30.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS,compile,0); if(compile[0]==0){ //若編譯失敗則顯示錯誤的日誌並刪除shader Log.e("ES20_ERROR","不能編譯著色器"+shaderType+":"); Log.e("ES20_ERROR",GLES30.glGetShaderInfoLog(shader)); GLES30.glDeleteShader(shader); shader=0; } } return shader; } //建立著色器程式的方法 public static int createProgram(String vertexSource,String fragmentSource) { //載入頂點著色器 int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexSource); if (vertexShader == 0) { return 0; } //載入片元著色器 int pixelShader=loadShader(GLES30.GL_FRAGMENT_SHADER,fragmentSource); if(pixelShader==0) { return 0; } //建立程式 int program=GLES30.glCreateProgram(); //若程式建立成功則向程式中加入頂點著色器與片元著色器 if(program!=0){ //向程式中加入頂點著色器 GLES30.glAttachShader(program,vertexShader); //向程式中加入片元著色器 GLES30.glAttachShader(program,pixelShader); checkGlError("glAttachShader"); //連線程式 GLES30.glLinkProgram(program); //存放連線成功program數量的陣列 int [] linkStatus=new int[1]; //獲取連線的情況 GLES30.glGetProgramiv(program,GLES30.GL_LINK_STATUS,linkStatus,0); //若連結失敗則報錯並刪除程式 if (linkStatus[0] != GLES30.GL_TRUE) { Log.e("ES20_ERROR", "Could not link program: "); Log.e("ES20_ERROR", GLES30.glGetProgramInfoLog(program)); GLES30.glDeleteProgram(program); program = 0; } } return program; } //檢查每一步操作是否有錯誤的方法 @SuppressLint("NewApi") public static void checkGlError(String op) { int error; while ((error = GLES30.glGetError()) != GLES30.GL_NO_ERROR) { Log.e("ES20_ERROR", op + ": glError " + error); throw new RuntimeException(op + ": glError " + error); } } //從sh指令碼中載入shader內容的方法 public static String loadFromAssetsFile(String fname,Resources r) { String result=null; try { InputStream in=r.getAssets().open(fname); 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 result; }
//從raw資料夾中讀取glsl檔案
public static String loadFromRawFile(Context context ,int resourceId){
StringBuilder body = new StringBuilder();
try {
InputStream inputStream =
context.getResources().openRawResource(resourceId);
InputStreamReader inputStreamReader =
new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String nextLine;
while ((nextLine = bufferedReader.readLine()) != null) {
body.append(nextLine);
body.append('\n');
}
} catch (IOException e) {
throw new RuntimeException(
"不能載入資源: " + resourceId, e);
} catch (Resources.NotFoundException nfe) {
throw new RuntimeException("資源沒有發現: " + resourceId, nfe);
}
return body.toString();
}
}
Triangle類程式碼
package com.opengl.a3_1_triangle;
import android.annotation.SuppressLint;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
/**
* Created by admin on 2016/11/13.
*/
public class Triangle {
Context context;
public static float [] mProjMatrix=new float[16];//4*4投影矩陣
public static float [] mVMatrix=new float[16];//攝像機位置朝向的引數矩陣
public static float[] mMVPMatrix;//最後起作用的總的變換矩陣
int mProgram;//自定義的渲染管執行緒序id
int muMVPMatrixHandle;//總的變換矩陣引用
int maPositionHandle;//頂點位置屬性的應用
int maColorHandle;//頂點顏色屬性的引用
String mVertexShader;//頂點著色器的程式碼指令碼
String mFragmentShader;//片元著色器程式碼指令碼
static float[] mMMatrix=new float[16];//具體物體的移動旋轉矩陣,包括旋轉,平移,縮放
FloatBuffer mVertexBuffer;//頂點座標資料緩衝
FloatBuffer mColorBuffer;//頂點著色資料緩衝
int vCount=0;
float xAngle=0;//繞x軸旋轉的角度
public Triangle(MyTDView mv, Context context){
this.context=context;
//呼叫初始化頂點資料的initVertexData的方法
initVertexData();
//呼叫初始化著色器的initShader的方法
// initShader(mv);
initShaderGLSL(mv);
}
public void initVertexData(){
//頂點座標資料的初始化
vCount=3;
final float UNIT_SIZE=0.2f;
float vertices[]=new float[]{
-4*UNIT_SIZE,0,0,
0,-4*UNIT_SIZE,0,
4*UNIT_SIZE,0,0,
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//設定位元組順序為本地作業系統順序
mVertexBuffer = vbb.asFloatBuffer();//轉換為浮點(Float)型緩衝
mVertexBuffer.put(vertices);//在緩衝區內寫入資料
mVertexBuffer.position(0);//設定緩衝區起始位置
float colors[]=new float[]//頂點顏色陣列
{
1,1,1,0,//白色
0,0,1,0,//藍
0,1,0,0//綠
};
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());//設定位元組順序為本地作業系統順序
mColorBuffer = cbb.asFloatBuffer();//轉換為浮點(Float)型緩衝
mColorBuffer.put(colors);//在緩衝區內寫入資料
mColorBuffer.position(0);//設定緩衝區起始位置
}
/*
//如果使用從sh指令碼中讀取著色器程式碼用這個程式碼
//初始化著色器的方法
@SuppressLint("NewApi")
public void initShader(MyTDView mv)
{
//載入頂點著色器的指令碼內容
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex.sh", mv.getResources());
//載入片元著色器的指令碼內容
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag.sh", mv.getResources());
//基於頂點著色器與片元著色器建立程式
mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
//獲取程式中頂點位置屬性引用
maPositionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition");
//獲取程式中頂點顏色屬性引用
maColorHandle= GLES30.glGetAttribLocation(mProgram, "aColor");
//獲取程式中總變換矩陣引用
muMVPMatrixHandle = GLES30.glGetUniformLocation(mProgram, "uMVPMatrix");
}
*/
//從指定的glsl格式讀取程式碼
public void initShaderGLSL(MyTDView mv)
{
// 載入頂點著色器的指令碼內容
mVertexShader = ShaderUtil.loadFromRawFile(context,
R.raw.vertex);
// 載入片元著色器的指令碼內容
mFragmentShader = ShaderUtil.loadFromRawFile(context,
R.raw.frag);
//基於頂點著色器與片元著色器建立程式
mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
//獲取程式中頂點位置屬性引用
maPositionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition");
//獲取程式中頂點顏色屬性引用
maColorHandle= GLES30.glGetAttribLocation(mProgram, "aColor");
//獲取程式中總變換矩陣引用
muMVPMatrixHandle = GLES30.glGetUniformLocation(mProgram, "uMVPMatrix");
}
@SuppressLint("NewApi")
public void drawSelf(){
//指定使用某套shader程式
GLES30.glUseProgram(mProgram);
//指定使用某套shader程式
GLES30.glUseProgram(mProgram);
//初始化變換矩陣
Matrix.setRotateM(mMMatrix,0,0,0,1,0);
//設定沿Z軸正向位移1
Matrix.translateM(mMMatrix,0,0,0,1);
//設定繞x軸旋轉
Matrix.rotateM(mMMatrix,0,xAngle,1,0,0);
//將變換矩陣傳入渲染管線
GLES30.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, Triangle.getFianlMatrix(mMMatrix), 0);
//將頂點位置資料傳送進渲染管線
GLES30.glVertexAttribPointer(
maPositionHandle,
3,
GLES30.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//將頂點顏色資料傳送進渲染管線
GLES30.glVertexAttribPointer
(
maColorHandle,
4,
GLES30.GL_FLOAT,
false,
4*4,
mColorBuffer
);
GLES30.glEnableVertexAttribArray(maPositionHandle);//啟用頂點位置資料
GLES30.glEnableVertexAttribArray(maColorHandle);//啟用頂點著色資料
//繪製三角形
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vCount);
}
public static float[] getFianlMatrix(float[] spec)
{
mMVPMatrix=new float[16];
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, spec, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
return mMVPMatrix;
}
}
MyTDView程式碼
package com.opengl.a3_1_triangle;
import android.content.Context;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by admin on 2016/11/13.
*/
public class MyTDView extends GLSurfaceView{
final float ANGLE_SPAN=0.375f;
RotateThread rthread;
SceneRenderer mRenderer;//自定義渲染器的引用
public MyTDView(Context context){
super(context);
this.setEGLContextClientVersion(3); //設定opengl es的版本為3
mRenderer=new SceneRenderer(context);
this.setRenderer(mRenderer);
this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//持續渲染模式 還有一種模式是當有請求時才渲染
}
private class SceneRenderer implements GLSurfaceView.Renderer
{
Context context;
Triangle tle;
public SceneRenderer(Context context) {
this.context=context;
}
public void onDrawFrame(GL10 gl) //繪製
{
//清除深度緩衝與顏色緩衝
GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);
//繪製三角形物件
tle.drawSelf();
}
public void onSurfaceChanged(GL10 gl, int width, int height) //當視窗更改的時候呼叫
{
//設定視窗大小及位置
GLES30.glViewport(0, 0, width, height);
//計算GLSurfaceView的寬高比
float ratio = (float) width / height;
//呼叫此方法計算產生透視投影矩陣
Matrix.frustumM(Triangle.mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 10);
//呼叫此方法產生攝像機9引數位置矩陣
Matrix.setLookAtM(Triangle.mVMatrix, 0, 0,0,3,0f,0f,0f,0f,1.0f,0.0f);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) //建立視窗
{
//設定螢幕背景色RGBA
GLES30.glClearColor(0,0,0,1.0f);
//建立三角形對物件
tle=new Triangle(MyTDView.this,context);
//開啟深度檢測
GLES30.glEnable(GLES30.GL_DEPTH_TEST);
rthread=new RotateThread();
rthread.start();
}
}
public class RotateThread extends Thread //自定義的內部類執行緒 重新發發起一個執行緒讓繞x軸旋轉
{
public boolean flag=true;
@Override
public void run()//重寫run方法
{
while(flag){
mRenderer.tle.xAngle=mRenderer.tle.xAngle+ANGLE_SPAN;
try {
Thread.sleep(20);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
頂點著色器的程式碼
#version 300 es
uniform mat4 uMVPMatrix;//總的變換矩陣
layout (location=0) in vec3 aPosition;//頂點的位置
layout (location=1) in vec4 aColor;//頂點顏色
out vec4 vColor;//用於傳遞給片元著色器的變數
void main()
{
gl_Position=uMVPMatrix*vec4(aPosition,1);
vColor=aColor;
}
片元著色器程式碼
#version 300 es
precision mediump float;
in vec4 vColor;//接受從頂點著色器過來的引數
out vec4 fragColor;//輸出到片元這顏色
void main(){
fragColor=vColor;//此片元的顏色值
}
MyActivity類程式碼package com.opengl.a3_1_triangle;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MyActivity extends Activity { //建立繼承Activity的主控制類
MyTDView mview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);//呼叫父類
//設定為豎屏模式
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mview=new MyTDView(this);//建立MyTDView類而物件
mview.requestFocus();
mview.setFocusableInTouchMode(true);
setContentView(mview);
}
@Override
public void onResume()//繼承Activity後重寫的onResume方法
{
super.onResume();
mview.onResume();//通過MyTDView類的物件呼叫onResume方法
}
@Override
public void onPause()//繼承Activity後重寫的onPause方法
{
super.onPause();
mview.onPause();//通過MyTDView類的物件呼叫onPause方法
}
}
相關推薦
opengl es3.0遊戲開發學習筆記1-繪製旋轉的三角形
前段時間一直在看opengl es2.0遊戲開發的知識 ,這幾天買了本opengl es3.0遊戲開發的書 打算一邊學習一邊整理學習筆記,我的開發環境是Android studio 2.1.3,不過有個問題是Android studio自帶的模擬器只能支援es2
cocos2d-x 3.x遊戲開發學習筆記(1)--mac下配置cocos2d-x 3.x開發環境
原文:http://blog.csdn.net/likendsl/article/details/34617725 開啟使用者目錄下.bash_profile檔案,配置環境 [python] view plaincopyprint? vim ~/.b
遊戲開發學習筆記三
nor scrip 筆記 nsrunloop posit ppr 遊戲開發 tor http sdk%E6%9B%B4%E6%96%B0%E4%B8%8D%E6%88%90%E5%8A%9F%E6%B1%82%E5%A4%A7%E7%A5%9E%E5%B8%AE%E5%BF
UWP開發學習筆記1
導航到頁面: this.Frame.Navigate(typeof(SecondPage)); 導航進入當前頁面時會呼叫OnNavigatedTo方法;導航從當前頁面離開時會呼叫OnNavigatingFrom方法導航時傳遞引數採用: this.Frame.Navigat
遊戲開發學習筆記(七)開發揹包系統
思路: Bag:管理揹包裡的格子 BagItemGrid:管理格子儲存物品的資訊(id及num) BagItem:管理物品拖拽功能及物品物品的更新顯示 Bag:管理揹包裡的格子 建立UI,Bag_item 和Bag_item_grid的Prefab, Bag新增Bag指令碼
【Unity 3D遊戲開發學習筆記】實現太陽系
目標: 寫一個程式,實現一個完整的太陽系, 其他星球圍繞太陽的轉速必須不一樣,且不在一個法平面上。 基本思路是在裡面建立物件,架構成一個太陽系,sun作為父物件,其他行星作為子物件,並且相對sun的初始位置均不一樣,那麼角速度相同的情況下轉速就不一樣了,另外
APP開發學習筆記(1)
什麼是APP 手機應用程式,通常是移動裝置(手機和平板的作業系統)應用程式的統稱。 APP的分類 IOS---------------------------------Objective-CAndroid---------------------------JavaW
JAVA串列埠開發學習筆記1
1、下載java Communications api開發包。2、將win32com.dll拷貝入C:\j2sdk1.4.2_04\bin3、將comm.jar拷貝入C:\j2sdk1.4.2_04\jre\lib\ext4、將javax.comm.properties拷
Unity 3D遊戲開發學習筆記(2) 牧師與魔鬼
遊戲事物: 3牧師,3惡魔,2河岸,河,船。 遊戲故事:3牧師和3惡魔需要用一艘船全部到達彼岸,但是船上和岸上都不能出現惡魔比牧師多的情形,否則惡魔會把牧師K.O,玩家輸掉比賽;直到所有牧師惡魔都到達對岸,玩家取得勝利。 MVC架構: IUser
Photon + Unity3D 線上遊戲開發 學習筆記(一)
大家好, 我也是學習Photon + unity3D 的新手 有什麼說錯的地方大家見諒哈, 我的開發環境是 unity3D 4.1.3 , Visual Studio 是2010 版本的 photon 用的是 V3 語言C# photon
【Unity3D遊戲開發學習筆記】(四)一切都動起來—Animator元件的應用
一、Animation簡介 動畫原本是指由許多連續的圖片在人眼前面快速播放,肉眼因視覺殘像產生錯覺,而誤以為畫面活動的作品。 但在 Unity3D 中的“ Animation”【動畫】 系統應該這樣理解——用於為遊戲者自動播放人物動作或自動演示物體運動路徑、色
【Unity3D遊戲開發學習筆記】(六)上帝之手—GameObject的操作
在Unity中,所有實體都屬於遊戲物件(GameObject),比如外部匯入到場景中的模型,Unity自帶的立方體等等,而要將這些GameOject進行管理,互動等操作,則需要用到指令碼來實現,上一節我們已經學習瞭如何建立一個指令碼並繫結到一個物體上,現在我們將
【Unity 3D遊戲開發學習筆記】粒子光環
實現如下圖的粒子光環: 參考網站:http://i-remember.fr/en 思路: 首先宣告定義一個類用於儲存每個粒子的半徑和角度 public class particleClass { public float radius =
小程式開發 學習筆記-1 (邏輯層、檢視層)
1、小程式包含一個描述整體程式的 app 和多個描述各自頁面的 page。 2、頁面的.json只能設定 window 相關的配置項,以決定本頁面的視窗表現,所以無需寫 window 這個鍵 邏輯層(App Service) 1、小程式開發框架的邏
【Unity3D遊戲開發學習筆記】(七)上帝之眼—第三人稱攝像機的簡單實現(跟隨視角,自由視角)
陸陸續續又開始更新自己的部落格,看來自我驅動能力還是不夠啊= =,廢話不多說了,之前的內容大概說了一下Unity的一些基礎知識,接下來我們將要對一些基本功能做一些學習。大家都知道,一個遊戲,少不了攝像機的參與(這不是廢話麼!沒攝像機怎麼玩!畫面都不呈現了好伐!)
Linux學習筆記1.0
Linux 基礎 知識積累 終端(terminal)物理終端(/dev/console) 控制臺console虛擬終端(/dev/tty[1-6]) tty:teletypewriters,可有n個,ctrl+alt+F[1-6]圖形終端(/dev/tty7)串行終端(/dev/ttyS#)偽終端
spring (4.0.2)——(尚矽谷)學習筆記1
aspect 什麽 企業應用 周期 持久層 非侵入 mvc 註入 JD 1、Spring是什麽? ①Spring 是一個開源框架; ②Spring 為簡化企業級應用開發而生。使用Spring可以使簡單的JavaBean實現以前只有EJB才能實現的功能。 ③Spr
Docker學習筆記1-從0創建並發布一個docker鏡像
雲計算 Docker Docker安裝略運行環境centos7先創建一個本地的目錄[root@localhost /]# mkdir nginx && cd nginx下載示例的配置文件留著備用[root@localhost nginx]# wget http://raw.github
Arduino 入門學習筆記1 開發環境及雙色LED實驗
本系列學習教程來自 創樂博智慧學習視訊 Arduino 發展 2005年,Massimo Banzi和David Cuartielles、David Mellis設計 Arduino。取該名稱的原因是Massimo Banzi喜歡去一家名叫Arduino的酒吧,其名稱是1000年
《Oracle PL/SQL開發指南》學習筆記1——Oracle PL/SQL程式開發概覽
本章內容: 1. PL/SQL的歷史和背景 2. Oracle開發架構 知識點: 1. SQL和PL/SQL的關係: The SQL language is the interface to the Oracle Database 12c database