OpenGL基礎39 GLSL內建變數與介面塊

2021-10-08 16:03:30 字數 3371 閱讀 2480

glsl有幾個以gl_為字首的變數(內建變數),它們在著色器中能直接獲取和使用,並且都有著很重要的意義,gl_position 和 gl_fragcoord 就是兩個典型的內建變數

gl_position:

頂點著色器裁切空間輸出的位置向量。想讓螢幕上渲染出東西,那麼就必須使用,否則將什麼都看不到,在第一次接觸頂點著色器之後,就一直在用它了

gl_pointsize:

渲染出的點的大小,需要滿足以下兩個條件,gl_pointsize才會是有效的:

它是乙個float變數,可以以畫素的方式設定點的高度和寬度,在著色器中描述每個頂點做為點被繪製出來的大小:

#version 330 core

layout (location = 0) in vec3 position;

layout (location = 1) in vec3 normal;

layout (location = 2) in vec2 texture;

out vec2 texin;

out vec3 normalin;

out vec3 fragposin;

uniform mat4 model; //模型矩陣

uniform mat4 view; //觀察矩陣

uniform mat4 projection; //投影矩陣

看上去比較驚悚,改變了繪製模式為gl_points,著色器修改如上:當頂點距離觀察者更遠的時候,它就會變得更大,後面的一些粒子效果也是通過這個實現的

gl_vertexid:

上面的gl_position和gl_pointsize都是輸出變數,它們的值是作為頂點著色器的輸出被讀取的,因此可以向它們寫入資料來影響結果,而gl_vertexid是乙個輸入變數,只能夠讀取

gl_vertexid是個整型變數,它儲存著我們繪製的當前頂點的id,當進行索引渲染(gldrawelements)時,這個變數儲存著當前繪製的頂點的索引,當用的不是索引繪製(gldrawarrays)時,這個變數儲存的是從渲染開始起直到當前處理的這個頂點的(當前頂點)編號,目前沒什麼用

gl_fragcoord:

在《opengl基礎29:深度測試》這一章就用過了,唯讀輸入變數vec4,其中x和y為視窗座標(別忘了opengl預設以左下為原點),其中小數部分恒為(0.5, 0.5),這是因為原點並非(0, 0)而是(0.5, 0.5)的原因,整數部分就是數第幾個畫素點了,若viewport範圍 為(0, 0, 2560, 1440)時, x, y 的取值範圍就為(0.5, 0.5, 2559.5, 1439.5);z座標為當前片元的深度資訊,由頂點座標系處理過後系統插值得到,第4個分量為 1/w

用這個可以實現很多好玩的東西,例如修改之前的天空盒著色器如下:

通過gl_fragcoord,就可以實現類似於分屏的效果,著色器可以給出2個完全不同的效果,乙個顯示在左半部分,乙個顯示在右半部分

gl_frontfacing:

在《opengl基礎32:面剔除》這一章中,知道了opengl如何根據頂點繪製順序判斷乙個面是正面還是背面,並在開啟面剔除後直接背面直接不進行繪製,而gl_frontfacing變數正能告訴我們當前片段是某個正面的一部分還是背面的一部分

有了這個之後,就可以對於乙個面的正反兩面,分別使用不同的紋理或者展現不同的效果

當然了,不要開啟面剔除,不然就毫無意義

gl_fragdepth:

上面的gl_fragcoord是唯讀的,不能修改它的值,而如果你想修改深度值,那麼也是ok的,glsl提供了乙個叫做gl_fragdepth的變數,可以用它在著色器中設定畫素的深度值

不過一旦設定了gl_fragdepth,opengl就會關閉所有的前置深度測試,因為opengl並不會知道你會設成什麼值

深度測試是在片段著色器已經模板測試執行之後,但是現在大部分的gpu都提供乙個叫做提前深度測試(early depth testing)的硬體特性,提前深度測試允許深度測試在片段著色器之前執行,只要清楚乙個片段永遠不會是可見的(它在其他物體之後),就能提前丟棄這個片段,是乙個很不錯的優化手段

這樣的話,設定gl_fragdepth就會影響opengl的效能

一環扣一環,如果我們能保證設定的深度值一定比gl_fragcoord.z更大或者更小,那麼其實opengl就可以不用關閉前置深度測試因為不影響結果,因此,在opengl4.x版本後,它允許我們做個承諾,以保證我們設定的gl_fragdepth值滿足一定條件

layout (depth_) out float gl_fragdepth:condition可以為以下4種之一

如果發現不能用,說明opengl的版本可能比較低

著色器之間傳資料通過 in 和 out 關鍵字,只需要在當前著色器中宣告乙個輸出,在下乙個著色器中宣告乙個同型別同名字的輸入就可以,當然,也可以將一堆資料報在乙個「塊」裡一起傳過去,和結構體很像,在這裡是介面塊(inte***ce blocks):

修改之前的著色器,非常簡單:

#version 330 core

layout (location = 0) in vec3 position;

layout (location = 1) in vec2 texture;

out vs_out

param;

uniform mat4 model; //模型矩陣

uniform mat4 view; //觀察矩陣

uniform mat4 projection; //投影矩陣

void main()

///#version 330 core

out vec4 color;

in vs_out

param;

uniform sampler2d texout;

void main()

傳遞資料只需要塊名一樣,不需要例項名相

如何在自己的opengl程式中使用GLSL

glsl,即gl shading language,用自己寫的程式取代opengl的固定渲染管線的一種語言。之前看了下rendermonkey,雖然功能不算弱,但使用rendermonkey卻不知道在裡面怎麼用自己的shader去渲染自己的opengl程式,所以就去找下了關於把shader鏈結到自己...

OpenGL基礎2 OpenGL簡介

小朋友你是否有很多問號,不知道為什麼需要這麼多複雜的方法,也不知道為什麼要這麼設計,更不知道僅僅顯示乙個點都那麼複雜,後面3d遊戲中的那麼精美的表現是否離自己很遠很遠 要不,再來一起看看opengl?其實看到這裡,你應該也像我一樣,裝好了環境,並且成功開啟了第乙個視窗,又或者說已經可以開始繪製一些非...

OPENGL紋理基礎

對於vbo道理是一樣的 1.紋理座標 在繪製一條線段時,我們設定其中乙個端點為紅色,另乙個端點為綠色,則opengl會自動計算線段中其它各畫素的顏色,如果是使用glshademode gl smooth 則最終會形成一種漸變的效果 例如線段中點,就是紅色和綠色的中間色 類似的,在繪製一條線段時,我們...