摘要:在一文了解中,我們了解到采用的是可編程渲染管線。新的頂點(diǎn)位置通過在頂點(diǎn)著色器中寫入傳遞到渲染管線的后繼階段繼續(xù)處理。頂點(diǎn)著色器中可以計(jì)算一個(gè)點(diǎn)的大小單位為像素,并將其賦值給類型以傳遞給渲染管線,如果沒有明確賦值的話,默認(rèn)值為。
OpenGL ES 構(gòu)建的三維空間,其中的三維
實(shí)體由許多的三角形拼接構(gòu)成
。如下圖左側(cè)所示的三維實(shí)體圓錐,其由許多三角形按照一定規(guī)律拼接構(gòu)成。而組成圓錐的每一個(gè)三角形,其任意一個(gè)頂點(diǎn)由三維空間中 x、y、z 三個(gè)坐標(biāo)分量來定義。
對(duì)于我們?nèi)粘J褂玫囊苿?dòng)手持設(shè)備,手機(jī)屏幕窗口由不連續(xù)的有限的二維像素小格子
構(gòu)成的,每一個(gè)像素格子有x、y兩個(gè)分量來定義。
因此在OpenGL ES繪制流程中,其主要工作是將三維空間中的坐標(biāo)點(diǎn)(x,y,z)構(gòu)成的三維圖形,轉(zhuǎn)化為手機(jī)屏幕上的二維像素點(diǎn)
。
這個(gè)轉(zhuǎn)化過程主要分為兩個(gè)步驟:
在OpenGL ES中,其大概的繪制流程如下圖所示:
這里將三維空間中構(gòu)成三維實(shí)體的坐標(biāo)信息,轉(zhuǎn)換為手機(jī)屏幕上有限的二維像素的過程
,便是由OpenGL ES渲染管線(Graphics Pipeline)來實(shí)現(xiàn)。
正文開始之前,需要先了解一下 OpenGL ES Shading Language 著色語言。
在《一文了解 OpenGL ES》中,我們了解到 OpenGL ES 3.x采用的是可編程渲染管線
。
OpenGL ES 3.x將頂點(diǎn)著色器
、片元著色器
的編碼權(quán)限開放給開發(fā)者。開發(fā)者需要使用OpenGL ES Shading Language(著色語言)
編碼實(shí)現(xiàn)頂點(diǎn)著色器
、片元著色器
處理邏輯,從而渲染出自己想的展示效果。
對(duì)于OpenGL ES Shading Language,我們有必要先了解一下OpenGL ES 與 OpenGL ES Shading Language 的對(duì)應(yīng)關(guān)系(了解對(duì)應(yīng)的API版本,才能編寫對(duì)應(yīng)版本要求的Shading Language腳本)。
OpenGL ES Version | GLSL Version |
---|---|
1.0 | -- |
1.1 | -- |
2.0 | 100 |
3.0 | 300 |
3.1 | 310 |
3.2 | 320 |
OpenGL ES 2.0
對(duì)應(yīng)的OpenGL ES Shading Language
版本為1.00
OpenGL ES 3.0
對(duì)應(yīng)的OpenGL ES Shading Language
版本為3.00
Shading Language 3.00 文檔:
https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf
各OpenGL ES版本API文檔:
https://www.khronos.org/registry/OpenGL/specs/es/
OpenGL ES中的渲染管線(OpenGL Rendering Pipeline)
指的是一系列的變換與渲染過程
,輸入
是需要渲染的3D物體的相關(guān)描述信息數(shù)據(jù)
(例:頂點(diǎn)坐標(biāo)、頂點(diǎn)顏色、頂點(diǎn)紋理等),經(jīng)過渲染管線,輸出一幀想要的圖像
。渲染管線
也稱之為渲染流水線
,由顯示芯片(GPU)內(nèi)部處理圖形信號(hào)的并行處理單元
組成,這些并行處理單元兩兩之間相互獨(dú)立,根據(jù)顯示芯片性能的不同處理單元的數(shù)量也存在很大的差異。將渲染工作通過顯示芯片中多個(gè)相互獨(dú)立的單元進(jìn)行并行處理后,渲染的效率可以大大提高。
OpenGL ES 3.x詳細(xì)的渲染管線如下圖所示:
該階段設(shè)定三維空間中物體的頂點(diǎn)坐標(biāo)
、頂點(diǎn)對(duì)應(yīng)的顏色
、頂點(diǎn)的紋理坐標(biāo)
等數(shù)據(jù),并且指定三維物體的繪制方式
,如:點(diǎn)繪制、線段繪制或者三角形繪制等。
頂點(diǎn)緩沖區(qū)在應(yīng)用程序中是可選的,對(duì)于某些在整個(gè)場(chǎng)景中頂點(diǎn)數(shù)據(jù)基本不變的情況,可以在初始化階段將頂點(diǎn)數(shù)據(jù)經(jīng)基本處理后送入頂點(diǎn)緩沖區(qū),在繪制每一幀想要的圖像時(shí)就省去了頂點(diǎn)數(shù)據(jù)IO的步驟,直接從頂點(diǎn)緩沖區(qū)中獲取頂點(diǎn)數(shù)據(jù)即可。相比于每次繪制時(shí)多帶帶將頂點(diǎn)數(shù)據(jù)送入GPU的方式,可以在一定程度上節(jié)省GPU的 IO 帶寬,提高渲染效率。
頂點(diǎn)著色器是一個(gè)可編程的處理單元
,功能為執(zhí)行頂點(diǎn)的變換
、光照
、材質(zhì)的應(yīng)用與計(jì)算
等頂點(diǎn)的相關(guān)操作
,每個(gè)頂點(diǎn)執(zhí)行一次
。
其工作過程為將原始的頂點(diǎn)幾何信息(頂點(diǎn)坐標(biāo)、顏色、紋理)
及其他屬性傳送到頂點(diǎn)著色器中,經(jīng)過自定義的頂點(diǎn)著色程序處理產(chǎn)生變化后的頂點(diǎn)位置信息,將變化后的頂點(diǎn)位置信息傳遞給后續(xù)圖元裝配階段,對(duì)應(yīng)的頂點(diǎn)紋理、顏色等信息則經(jīng)光柵化后傳遞到片元著色器。
頂點(diǎn)著色器
替代了原有固定管線
(OpenGL 1.x采用固定渲染管線)的頂點(diǎn)變換、光照計(jì)算
,采用 著色語言進(jìn)行開發(fā)(OpenGL ES Shading Language) ,開發(fā)人員可以根據(jù)自己的需求采用著色語言自行開發(fā)頂點(diǎn)變換、光照等功能,大大增加了程序的靈活性。
不同于OpenGL ES 2.0中,頂點(diǎn)著色器輸入為attribute(屬性變量)
,輸出為varying(易變變量)
。
在OpenGL ES3.0中,頂點(diǎn)著色器的輸入主要為待處理頂點(diǎn)相應(yīng)的in(輸入屬性)
、uniform(統(tǒng)一變量)
、采樣器以及臨時(shí)變量
,輸出主要為經(jīng)過頂點(diǎn)著色器后生成的out(輸出屬性)
及一些內(nèi)建輸出變量
。
uniform(統(tǒng)一變量)
:同一組頂點(diǎn)組成的三維物體其所有頂點(diǎn)屬性都相同的屬性量
,一般為場(chǎng)景中當(dāng)前的光源位置
、當(dāng)前的攝像機(jī)位置
、投影系列矩陣
等,,可以使用 uniform (統(tǒng)一變量) 傳入頂點(diǎn)著色器。in(輸入屬性)
頂點(diǎn)的位置
、顏色
、法向量
等,每個(gè)頂點(diǎn)各自不同的信息都是以attribute變量的方式傳入頂點(diǎn)著色器的。out(輸出屬性)
從頂點(diǎn)著色器傳遞到片元著色器的量
,如 用于傳遞到片元著色器中的頂點(diǎn)顏色,可以使用out (輸出屬性)。輸出到OpenGL ES渲染管線的數(shù)據(jù)變量
。輸出到OpenGL ES渲染管線的數(shù)據(jù)變量
。頂點(diǎn)著色器代碼舉例
著色器采用OpenGL ES Shading Language編寫,為一種類C的編程語言,頂點(diǎn)著色器代碼實(shí)現(xiàn)舉例如下:
詳細(xì)了解著色語言語法,可查看khronos
官方:
OpenGL ES Shading Language 3.00:
https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf
// 頂點(diǎn)著色器程序舉例如下:#version 300 es // 為著色語言版本v3.00,必須出現(xiàn)在第一行// 總變換矩陣uniform mat4 uMVPMatrix; // 頂點(diǎn)位置in vec3 aPosition; // 頂點(diǎn)顏色in vec4 aColor; // 用于傳遞給片元著色器的變量out vec4 vColor; void main() { // 根據(jù)總變換矩陣計(jì)算此次繪制此頂點(diǎn)位置 gl_Position = uMVPMatrix * vec4(aPosition,1); // 將接收的顏色傳遞給片元著色器 vColor = aColor; }
uniform(統(tǒng)一變量)
uniform mat4 uMVPMatrix; 總變換矩陣
。in(輸入屬性)
out(輸出屬性)
out vec4 vColor; 頂點(diǎn)顏色
。內(nèi)建輸出變量
注:
輸出屬性(頂點(diǎn)顏色、紋理)在頂點(diǎn)著色器賦值后并不直接賦值到片元著色器中,而是經(jīng)由光柵化階段處理。將三維世界由頂點(diǎn)數(shù)據(jù)構(gòu)成的物體離散為二維世界一個(gè)個(gè)像素點(diǎn),片元著色器處理的數(shù)據(jù)是已經(jīng)離散到二維顯示平面上的一個(gè)個(gè)離散的像素點(diǎn)(每個(gè)像素點(diǎn)為一個(gè)片元)
。而這個(gè)離散過程中位于兩個(gè)頂點(diǎn)之間的像素頂數(shù)據(jù)(顏色值、紋理數(shù)據(jù)),大多在光柵化階段差值計(jì)算產(chǎn)生
。
上圖中,展示的是一個(gè)自上而下
從黑到白的一個(gè)漸變?nèi)切?/code>。
在OpenGL ES的輸入中,僅僅輸入了三個(gè)頂點(diǎn)顏色值,頂點(diǎn)1 (0,0,0) 黑色、,頂點(diǎn)2 (1,1,1) 白色、頂點(diǎn)3 (1,1,1) 白色。而在三角形在光柵化階段,投影到屏幕上之前,其他部分的顏色是由這三個(gè)輸入頂點(diǎn)顏色值差值計(jì)算產(chǎn)生的
,例如:三角形高二分之一處的點(diǎn)顏色差值計(jì)算的結(jié)果為 (0.5,0.5,0.5) 灰色。
變化反饋能夠?qū)?“頂點(diǎn)著色器” 的計(jì)算結(jié)果輸出,也就是可以將大量的向量、矩陣等運(yùn)算交給GPU來運(yùn)行,在一定程度上節(jié)省CPU的運(yùn)算量。變化反饋的計(jì)算結(jié)果,可以輸出到一個(gè)緩沖區(qū)中,該緩沖區(qū)中的內(nèi)容還可作為另一個(gè) “頂點(diǎn)著色器” 程序的輸入數(shù)據(jù)。
在這個(gè)階段,主要有兩個(gè)任務(wù),一個(gè)是圖元組裝
,另一個(gè)是圖元處理
。
圖元組裝
是頂點(diǎn)數(shù)據(jù)被結(jié)合成完整的圖元。圖元處理
最重要的是剪裁
,其任務(wù)是消除位于顯示區(qū)域之外的部分
幾何圖元。視椎體
內(nèi),則傳遞圖元進(jìn)行后面的處理;視椎體
內(nèi),則剪裁
該圖元(剪裁圖元可能會(huì)額外增加頂點(diǎn)
數(shù)據(jù))。視椎體
外,則丟棄該圖元,以節(jié)省GPU性能。光柵化就是將三維空間中連續(xù)的數(shù)學(xué)圖形
,柵格化為二維顯示平面上一個(gè)個(gè)像素點(diǎn)
的過程。
將由三維
頂點(diǎn)信息組成的幾何圖元
,柵格化
為幀緩沖區(qū)中由無數(shù)像素點(diǎn)
構(gòu)成的二維圖像
。這里,最終生成的幀緩沖區(qū)中每一個(gè)像素點(diǎn)
都被看做一個(gè)片元
。
例如,一條直線可能在屏幕上包含了5個(gè)像素,而光柵化就是將這條直線轉(zhuǎn)化為5個(gè)片元,每個(gè)片元由頂點(diǎn)坐標(biāo)、頂點(diǎn)顏色、頂點(diǎn)紋理坐標(biāo)以及頂點(diǎn)的深度等信息組成。
光柵化實(shí)際是由以下兩個(gè)過程組成:
片元著色器
是用于處理片元相關(guān)數(shù)據(jù)的可編程單元
,可以執(zhí)行紋理的采樣
、顏色的匯總
、計(jì)算霧顏色
等操作,每片元執(zhí)行一次(每個(gè)像素執(zhí)行一次)
。片元著色器
可編程單元替換了OpenGL ES 1.x固定渲染管線階段中紋理顏色求和
、霧以及Alpha測(cè)試
等階段,被其替代的功能將需要由開發(fā)人員用著色器語言編碼完成。
頂點(diǎn)著色器每頂點(diǎn)執(zhí)行一次
,片元著色器每片元[像素]執(zhí)行一次
。
一般情況下片元的數(shù)量遠(yuǎn)遠(yuǎn)大于構(gòu)成三維物體頂點(diǎn)的數(shù)量(例如:一個(gè)三角形由三個(gè)頂點(diǎn)數(shù)據(jù)構(gòu)成,光柵化到屏幕上時(shí),卻有成百上千個(gè)像素點(diǎn)構(gòu)成),因此片元著色器的執(zhí)行次數(shù)明顯大于頂點(diǎn)著色器的執(zhí)行次數(shù),開發(fā)中為提高運(yùn)行效率,應(yīng)盡量減小片元著色器的運(yùn)算量
,將一些復(fù)雜運(yùn)算放在頂點(diǎn)著色器中執(zhí)行
。
out(輸出屬性)
頂點(diǎn)著色器傳遞到片元著色器的數(shù)據(jù)變量
,如頂點(diǎn)著色器所介紹,由系統(tǒng)在頂點(diǎn)著色器后的光柵化階段自動(dòng)插值產(chǎn)生。out屬性變量個(gè)數(shù)隨需求而定,并沒有硬性的變量數(shù)量上限限制。out vec4 fragColor
內(nèi)建變量gl_FragColor
,OpenGL ES 3.0最終片元的顏色輸出到輸出屬性fragColor
。片元著色器代碼舉例
著色器采用OpenGL ES Shading Language編寫,為一種類C的編程語言,片元著色器代碼實(shí)現(xiàn)舉例如下:
詳細(xì)了解著色語言語法,可查看khronos
官方:
OpenGL ES Shading Language 3.00:
https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf
// 片元著色器舉例(每個(gè)片元[像素]執(zhí)行一次)#version 300 es // 為著色語言版本v3.00,必須出現(xiàn)在第一行precision mediump float;// 接收從頂點(diǎn)著色器過來的參數(shù)(具體數(shù)值由光柵化階段差值產(chǎn)生)out vec4 vColor; // 輸出到的片元顏色out vec4 fragColor void main() { //片元的最終賦值 fragColor = vColor;}
varying(易變變量)
varying vec4 vColor
out vec4 fragColor
內(nèi)建變量gl_FragColor
,OpenGL ES 3.0最終片元的顏色輸出到輸出屬性fragColor
。fragColor = vColor
。如果程序中啟用了剪裁測(cè)試,OpenGL ES 會(huì)檢查每個(gè)片元在幀緩沖中對(duì)應(yīng)的位置,若對(duì)應(yīng)位置在剪裁窗口中則將此片元送入下一階段,否則丟棄此片元。。
深度測(cè)試是在片元處理過程中通過測(cè)試一個(gè)片元在視椎體
的深度坐標(biāo),來判斷它是否被更小深度坐標(biāo)的片斷遮擋而決定是否真去繪制它(開啟深度測(cè)試有助于節(jié)省GPU性能);沒有深度測(cè)試,物體展現(xiàn)與否就會(huì)取決于繪制順序而不是擺放的坐標(biāo)。
// 在Android中打開深度測(cè)試GLES30.glEnable(GLES20.GL_DEPTH_TEST);
模板測(cè)試的主要功能為將繪制區(qū)域限定在一定的范圍內(nèi),一般用在湖面倒影、鏡像等場(chǎng)合。
模板測(cè)試涉及到一個(gè)詞模板緩沖區(qū)
(Stencil Buffer)。在模板緩沖中,通常每個(gè)模板值(Stencil Value)是8位的,所以每個(gè)片元一共能有256種不同的模板值。
使用時(shí),我們可以先將模板緩沖區(qū)刷成個(gè)某個(gè)固定的值,然后進(jìn)行圖像繪制,完成繪制后模板緩沖區(qū)中的值可能會(huì)被污染[污染],此時(shí)開發(fā)者就可以選擇丟棄或是保留這些被污染的片段,從而構(gòu)造湖面倒影或者鏡像。
經(jīng)過前面的幾個(gè)階段,已經(jīng)產(chǎn)生了候選片元,而候選片元最終要進(jìn)入幀緩沖成為像素。
在候選片元進(jìn)入幀緩沖區(qū)成為像素的過程中:
抖動(dòng)是一種簡(jiǎn)單的操作,是一種在色彩空間較小的設(shè)備上展示較大色彩空間的圖像的一種方法。
例如:在一個(gè)RGB_565
的設(shè)備上展示RGB_888
的圖像,展示時(shí)如果簡(jiǎn)單進(jìn)行數(shù)據(jù)截?cái)辔唬瑫?huì)造成色彩的失真和生硬。抖動(dòng)使用一個(gè)矩陣,來調(diào)整一個(gè)像素周圍的像素的值,來使人眼產(chǎn)生錯(cuò)覺,而模擬
出原來的色彩。
這種技巧,對(duì)于只支持8位或者16位顏色信息的顯示系統(tǒng)中非常有用。
// 開啟抖動(dòng)GLES30.glEnable(GLES20.GL_DITHER);
OpenGL ES的物體繪制并不是直接回執(zhí)在屏幕上的,而是預(yù)先在幀緩沖區(qū)中進(jìn)行繪制,每一繪制完成一幀再將繪制的結(jié)果交換到屏幕上。因此,每次繪制新的一幀數(shù)據(jù)時(shí)都需要清理緩沖區(qū)中的相關(guān)數(shù)據(jù),否則可能產(chǎn)生錯(cuò)誤的顯示效果。
OpenGL ES Shading Language 3.00:
https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf
OpenGL ES 3.0 API:
https://www.khronos.org/registry/OpenGL-Refpages/es3.0/
gl_pipeline:
http://www.songho.ca/opengl/gl_pipeline.html
learnopengl:
https://learnopengl-cn.github.io/01%20Getting%20started/01%20OpenGL/
GLSL詳解:
https://zhuanlan.zhihu.com/p/349296191
OpenGL ES 變換反饋:
https://www.shangmayuan.com/a/4a48e882e765411b8597e12c.html
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/124821.html
摘要:管線優(yōu)化管線優(yōu)化曲面細(xì)分期間消除子像素。然而,高級(jí)別的曲面細(xì)分可以產(chǎn)生子像素三角形,這導(dǎo)致光柵化利用率降低。另外,如果合并或批處理之后的物體包圍盒過大,反而會(huì)造成性能下降,因?yàn)闊o法有效使用遮擋剔除等技術(shù)進(jìn)行剔除。? 目錄 12.6 移動(dòng)端渲染優(yōu)化 12.6.1 渲染管線優(yōu)化 12.6.1.1 使用新特性 12.6.1.2 管線優(yōu)化 ...
摘要:下面是頂點(diǎn)及片元著色器程序,用字符串表示,它將直接運(yùn)行在瀏覽器之上。最后,使用將和著色器連接。創(chuàng)建著色器對(duì)象創(chuàng)建編程對(duì)象賦值已創(chuàng)建的著色器對(duì)象連接編程對(duì)象檢查鏈接結(jié)果鏈接程序失敗使用可用著色器程序這一步主要使用方法告訴使用程序。 該文章于一天前發(fā)表在 github,若有問題可提至 github。 目前,我們有很多方案可以快速的接觸到 WebGL 并繪制復(fù)雜的圖形,但最后發(fā)現(xiàn)我們忽視了很...
摘要:而且,如果將鏡頭大幅度遠(yuǎn)離蘋果,那么也有可能看不到蘋果了。著色器又分為兩種頂點(diǎn)著色器顧名思義它能處理頂點(diǎn)坐標(biāo)大小等矩陣計(jì)算后的結(jié)果,能夠把數(shù)學(xué)坐標(biāo)光柵化。 我對(duì)webgl或者說二維、三維的理解 首先我們要做的就是把三維的東西展現(xiàn)在顯示器里(瀏覽器里),但瀏覽器是二維的。那么就是把一個(gè)三維的物體用數(shù)學(xué)模型描述出來(x,y,z)然后把這個(gè)三維的數(shù)學(xué)模型轉(zhuǎn)換到二維的瀏覽器里顯示出來。(用we...
摘要:這是視覺專題的第一篇,將分為什么是語法說明渲染管線程序渲染流程分析這幾個(gè)小模塊來一一介紹,閱讀完本篇內(nèi)容你將收獲是什么渲染管線的工作流程友情提示該篇文字較多,比較適合對(duì)知之甚少的同學(xué)閱讀,已經(jīng)有相關(guān)經(jīng)驗(yàn)的大佬可以溜了這是 視覺專題 的第一篇,將分為: 什么是 OpenGL OpenGL 語法說明 OpenGL 渲染管線 OpenGL 程序&渲染流程分析 這幾個(gè)小模塊來一一介紹,閱讀完本篇...
閱讀 3538·2021-11-24 09:39
閱讀 795·2019-08-30 14:22
閱讀 3044·2019-08-30 13:13
閱讀 2330·2019-08-29 17:06
閱讀 2934·2019-08-29 16:22
閱讀 1268·2019-08-29 10:58
閱讀 2441·2019-08-26 13:47
閱讀 1641·2019-08-26 11:39