目錄 一.嵌入式設備的 OpenGL ES 版本 二.相容性 三.著色器腳本 1.OpenGL ES shader 2.0 2.OpenGL ES shader 3.0 3.版本聲明 4. 預設精度修飾符 precision 4.輸入輸出 5.變數賦值 四.關於頂點緩衝區對象 VBO 與頂點數組對象 ...
目錄
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 特效
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 轉場
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 函數
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES GPUImage 使用
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES GLSL 編程
一.嵌入式設備的 OpenGL ES 版本
OpenGL ES 1.x 支持 初代 iPhone 和 Android;
OpenGL ES 2.0 支持 Android 2.2 以後的平臺,支持 iPad , iPhone3GS 和後續版本,以及 iPodTouch3 代和後續版本。
OpenGL ES 3.0 支持 Android 4.3 以後的平臺。支持 iPhone 5s ,iPad Air ,iPad mini 2 及後續版本。
二.相容性
OpenGL ES 3.0 是向下相容 OpenGL ES 2.0 的。也就是說使用 2.0 編寫的應用程式是可以在 3.0 中繼續使用的。
三.著色器腳本
1.OpenGL ES shader 2.0
//頂點著色器
attribute vec4 aPosition; // 應用程式傳入頂點著色器的頂點位置
attribute vec2 aTextureCoord; // 應用程式傳入頂點著色器的頂點紋理坐標
varying vec2 vTextureCoord; // 用於傳遞給片元著色器的頂點紋理數據
void main()
{
gl_Position = aPosition; // 此次繪製此頂點位置
vTextureCoord = aTextureCoord; // 將接收的紋理坐標傳遞給片元著色器
}
//片元著色器
precision mediump float; // 設置工作精度
varying vec2 vTextureCoord; // 接收從頂點著色器過來的紋理坐標
uniform sampler2D sTexture; // 紋理採樣器,代表一幅紋理
void main()
{
gl_FragColor = texture2D(sTexture, vTextureCoord);// 進行紋理採樣
}
2.OpenGL ES shader 3.0
//頂點著色器
#version es 300
uniform mat4 u_matViewProj;
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_color;
out vec3 v_color;
void main() {
gl_Position = u_matViewProj * a_position;
v_color = a_color;
}
//片元著色器
#version es 300
precision mediump float;
in vec3 v_color; // input form vertex shader
layout(location = 0) out vec4 o_fragColor;
void main() {
o_fragColor = vec4(v_color, 1.0);
}
3.版本聲明
在 OpenGL ES 3.0 中,頂點著色器和片段著色器的第一行必須聲明著色器版本,否則編譯報錯:
ERROR: 0:1: '' : syntax error: #version directive must occur in a shader before anything
在 OpenGL ES 3.0 中,可以必須聲明著色器版本:
#version es 300
在 OpenGL ES 2.0 中,可以不用聲明著色器版本,預設為:
#version es 100
備註: 以往 2.0 剛剛出來可編程的圖形管線,所以版本聲明為 #version 100 es ,後來為了使版本號相匹配,OpenGL ES 3.0 的 shader 版本直接從 1.0 跳到了 3.0 。
#version 300 es 指定使用OpenGL3.0
#version 100 es 指定使用OpenGL2.0 (不指定version 預設為OpenGL2.0)
4. 預設精度修飾符 precision
在頂點語言中有如下預定義的全局預設精度語句:
precision highp float;
precision highp int;
precision lowp sampler2D;
precision lowp samplerCube;
在片元語言中有如下預定義的全局預設精度語句:
precision mediump int;
precision lowp sampler2D;
precision lowp samplerCube;
片元語言沒有預設的浮點數精度修飾符。因此,對於浮點數,浮點數向量和矩陣變數聲明,要麼聲明必須包含一個精度修飾符,要不預設的精度修飾符在之前已經被聲明過了
precision highp float;
4.輸入輸出
OpenGL ES 3.0 中新增了** in,out,inout **關鍵字,用來取代 **attribute 和 varying **關鍵字。
同時 gl_FragColor 和 gl_FragData 也刪除了,片段著色器可以使用 out 聲明欄位輸出。
5.變數賦值
OpenGL ES 3.0 中可以直接使用 layout 對指定位置的變數賦值。例如:
shader腳本中
layout (location = 1) uniform float a;
代碼中,直接寫上對應的 layout 的值就可以賦值
GLES30.glUniform1f(1, 1f);
而 OpenGL ES 2.0 中必須使用如下形式賦值:
GLES20.glUniform1f(GLES20.glGetAttribLocation(program, "a"), 1f)
四.關於頂點緩衝區對象 VBO 與頂點數組對象 VAO
VAO (頂點數組對象:Vertex Array Object)是指頂點數組對象,主要用於管理 VBO 或 EBO ,減少 glBindBuffer 、glEnableVertexAttribArray、 glVertexAttribPointer 這些調用操作,高效地實現在頂點數組配置之間切換。
**VBO(頂點緩衝區對象: Vertex Buffer Object)是指把頂點數據保存在顯存中,繪製時直接從顯存中取數據,減少了數據傳輸的開銷,**因為頂點數據多了,就是坐標的數據多了很多的很多組,切換的時候很麻煩,就出現了這個 VAO,綁定對應的頂點數據
OpenGL 2.0 有 VBO,沒有 VAO,VAO 是 OpenGL 3.0 才開始支持的,並且在 OpenGL 3.0 中,強制要求綁定一個 VAO 才能開始繪製。
例如:在 OpenGL 3.0 中,不使用 VAO ,調用完 glVertexAttribPointer, glGetError 報錯 GL_INVALID_OPERATION。
int pos_location = glGetAttribLocation(ProgramId, "position");
glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices);
查看 OpenGL 官方文檔 http://docs.gl/gl3/glVertexAttribPointer
GL_INVALID_OPERATION is generated in the core context if there is no Vertex Array Object bound
在 OpenGL 3.0 中,強制要求綁定一個 VAO 才能開始繪製。因此,需要在程式初始化的時候,創建並綁定一個 VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
此外,OpenGL 3.0 中也不允許在 glVertexAttribPointer 直接傳數組了,因此要把頂點先傳入 vbo 中
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);
綁定 VBO 之後,glVertexAttribPointer 後面的 pointer 參數就要填 0 了。
glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0);
五.PBO
OpenGL 2.0 不支持 PBO ,3.0 支持 PBO , PBO 設計的目的就是快速地向顯卡傳輸數據,或者從顯卡讀取數據,我們可以使用它更加高效的讀取屏幕數據。
單個 PBO 讀取屏幕數據效率大概和 glReadPixels 差不多,雙 PBO 交換讀取效率會很高。
原因是使用 PBO 時,屏幕上的數據不是讀取到記憶體,而是從顯卡讀到 PBO 中,或者如果內部機制是讀取到記憶體中,但這也是由 DMA 控制器來完成的,而不是 cpu 指令來做的,再加上兩個 PBO 交換使用,所以讀取效率很高。
PBO 快速地從記憶體 CPU 向顯卡 GPU 傳輸數據 —> GL_PIXEL_PACK_BUFFER
**PBO 快速地從顯卡 GPU 讀取數據到記憶體 CPU** —> GL_PIXEL_UNPACK_BUFFER
六.猜你喜歡
本文由博客 - 猿說編程 猿說編程 發佈!