前言
在上一篇文章中我們學習了 GLSL ES 的數據類型,那麼本章節學習的是 GLSL ES 中運算符和限定符的內容。
在本系列文章中主要針對 GLSL ES 3.0 進行講解。
正文
運算符(Operators)
使用括號包裹的內容優先級最高!
優先級 | 操作符 | 描述 |
---|---|---|
1 | ++ -- |
後置自增、自減 |
2 | ++ -- |
前置自增、自減 |
2 | + - ~ ! |
一元運算 |
3 | * % / |
乘、取餘、除 |
4 | + - |
加、減 |
5 | << >> |
位運算 |
6 | < > <= >= == != |
關係運算 |
7 | & ^ | |
位與、位異或、位同或 |
8 | && ^^ || |
邏輯與、邏輯異或、邏輯同或 |
9 | ?: |
三目運算 |
10 | = |
賦值 |
10 | += -= *= /= %= <<= >>= &= ^= |= |
算術賦值 |
限定符(Qualifiers)
儲存限定符(Storage Qualifiers)
聲明變量時可以在類型前面添加一個儲存限定符。
限定詞 | 含義 |
---|---|
無(默認) | 用於局部作用域。 |
const | 聲明爲只讀的常量。 |
in | 從上一階段輸入到當前着色器。 |
out | 從當前着色器輸出到下一階段。 |
uniform | 在着色器、OpenGL ES 和程序之間共享的變量。 |
const
使用 const
限定符修飾的變量即爲常量,常量一但定義就不可再修改。
適用於標量、向量、矩陣、數組和結構體,但不適用於採樣器:
// 聲明定義常量
const int age = 18;
const vec4 color = vec4(0.5, 0.5, 0.5, 0.5);
// 也可以用於限定函數的參數
void doSomething(const float param) {
param = 0.1; // Error! 不可!
// ...
}
in
in
限定符常用於接收從上一階段輸出的變量:
in vec3 a_position; // 接收一個頂點座標向量
in vec2 a_uv0; // 接收一個紋理座標向量
in vec4 a_color; // 接受一個顏色向量
out
out
限定符常用於將當前着色器中的變量輸出到下一階段:
out vec2 v_uv0; // 輸出一個紋理座標向量
out vec4 v_color; // 輸出一個顏色向量
uniform
使用 uniform
限定符來表示一個統一且只讀的全局變量,該變量爲所有着色器所共用。
注意:聲明瞭卻沒有使用的 uniform 變量會在編譯時被靜默移除!
uniform sampler2D texture;
另外 uniform
變量只能在程序中使用 OpenGL ES 的一系列 glUniform
API 進行賦值:
// 程序代碼
int location = glGetUniformLocation(shaderProgram, "color"); // 查找 color 的位置(索引)
glUniform4f(location, 0.0f, 0.1f, 0.0f, 1.0f); // 給 color 賦值
// 着色器代碼
uniform vec4 color; // vec4(0.0, 0.1, 0.0, 1.0)
參數限定符(Parameter Qualifiers)
函數的參數也可以使用限定符。
限定詞 | 含義 |
---|---|
無(默認) | 和 in 的作用一致。 |
in |
表示複製進函數體內的參數(值傳遞,不影響原來的值)。 |
out |
表示函數向外複製的參數,必須是之前未被初始化的變量(引用傳遞,會影響原來的值)。 |
inout |
表示參數將在函數內外保持一致(引用傳遞,會影響原來的值)。 |
使用示例:
// in
void doo(in float param) { ... } // 和普通不加限定詞的參數一樣
// out
void foo(out int param) {
param = 666;
}
int a; // 聲明瞭但是沒有初始化
foo(a); // a = 666
// inout
void goo(inout int param) {
param = param++;
}
int b = 1;
goo(b); // b = 2
精度限定符(Precision Qualifiers)
浮點數、整數和採樣器類型聲明可以添加精度限定詞來設置精度範圍(精度控制可以擴展至向量和矩陣)。
精度限定符不適用於常量、布爾類型和構造函數!
限定詞 | 含義 |
---|---|
highp |
滿足頂點語言的最低要求(使用 highp 可以獲得最大的範圍和精度,但是也有可能會降低運行速度)。 |
mediump |
範圍和精度介於 highp 和 lowp 之間(通常用於儲存高範圍的顏色數據和低精度的幾何數據)。 |
lowp |
範圍和精度比 meduimp 小,但是足以儲存所有 8-bit 顏色數據。 |
// 變量聲明
lowp float a;
mediump vec2 p;
highp mat4 m;
// 函數聲明(返回值和參數)也適用
highp float foo(highp param);
默認精度限定符(Default Precision Qualifiers)
我們可以用 precision
關鍵字來聲明指定類型的默認精度:
// 聲明方式
precision 精度限定符 類型;
// 示例:聲明 float 類型的默認精度爲 highp
precision highp float;
在未主動聲明精度的情況下,在頂點着色器中有以下默認精度聲明:
precision highp float;
precision highp int;
precision lowp sampler2D;
precision lowp samplerCube;
而在片段着色器中有以下默認精度聲明:
precision mediump int;
precision lowp sampler2D;
precision lowp samplerCube;
在片段着色器中浮點類型、浮點向量和浮點矩陣都沒有默認的精度,所以使用時就必須聲明其精度,或者事先聲明默認精度!
另外,上面沒有提到的類型都沒有默認精度!
相關資料
OpenGL ES Registry(OpenGL ES 資料頁)
https://www.khronos.org/registry/OpenGL/index_es.php
OpenGL ES 3 Quick Reference Card(OpenGL ES 3 快速參考卡片)
https://www.khronos.org/files/opengles3-quick-reference-card.pdf
GLSL ES Specification 3.00(GLSL ES 規範 3.0)
https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf
OpenGL ES 3.0 Online Reference Pages(OpenGL ES 3.0 在線參考頁)
https://www.khronos.org/registry/OpenGL-Refpages/es3.0/
傳送門
更多分享
公衆號
菜鳥小棧
我是陳皮皮,這是我的個人公衆號,專注但不僅限於遊戲開發、前端和後端技術記錄與分享。
每一篇原創都非常用心,你的關注就是我原創的動力!
Input and output.