Shader 入門:GLSL ES(運算符和限定符)

前言

在上一篇文章中我們學習了 GLSL ES 的數據類型,那麼本章節學習的是 GLSL ES 中運算符和限定符的內容。

上一篇:《Shader 入門: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 範圍和精度介於 highplowp 之間(通常用於儲存高範圍的顏色數據和低精度的幾何數據)。
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/


傳送門

微信推文版本

個人博客:菜鳥小棧

開源主頁:陳皮皮

Eazax-CCC 遊戲開發腳手架


更多分享

爲什麼選擇使用 TypeScript ?

高斯模糊 Shader

一文看懂 YAML


公衆號

菜鳥小棧

我是陳皮皮,這是我的個人公衆號,專注但不僅限於遊戲開發、前端和後端技術記錄與分享。

每一篇原創都非常用心,你的關注就是我原創的動力!

Input and output.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章