注:本文檔只記錄要點和我自己的一些新得,並不是教程。需要教程的請去看OpenGLLearn原文。
混合可以實現物體透明度。
實現透明度由兩種方式:
1是拋棄(discard)一部分片段,這種情況下,不存在半透明的片段。
2纔是真正意義上的混合。將當前片段,和目標片段,按照一定的公式,進行加權計算。
【1】
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D texture1;
void main()
{
vec4 texColor = texture(texture1, TexCoords);
if(texColor.a < 0.1)
discard;
FragColor = texColor;
}
丟棄片段的比較暴力了,直接判斷alpha<某個常亮的片段,丟棄掉,不過這個if會產生邏輯分支,所以效率也就那樣吧……
環繞紋理設置成:GL_CLAMP_TO_EDGE 可以略微提高視覺效果。
【2】混合
激活混合用:glEnable(GL_BLEND);
那一大丟丟的參數,其實最常用的也就只有:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
也就是源alpha 和 1-源alpha
這裏glBlendFunc是混合操作設置函數。
glBlendFuncSeparate更爲鬼畜一些,他可以爲顏色和Alpha分別設置操作函數。
這兩個都是設置源和目標,如何處理rgb和alpha值的。
glBlendEquation可以用來設置混合運算符。其實最常用的也就是GL_FUNC_ADD
這個函式,是設置用哪個公式去處理這些alpha和RGB值的。
混合的原理:
前提是你已經在混合之前畫過一些東西(哪怕只天空盒也OK),不然混合個毛線?
混合的時候,將要繪製的東西是Source,已經畫完的東西是Target。
混合的時候,你的Shader裏面幾乎不用改什麼東西,片段會按照混合公式和數值規則,自己去和已經繪製好的片段進行混合。Unity則是在用ShaderLab的語法去設置這些函式的.
之前遇到過的一個問題的解釋:
幾個月以前,我曾經遇到過一個問題,在我用WorldCreatorPro製作地圖的時候,在沒有使用SpeedTree而使用切片LOD的時候,也就是離的比較遠的時候,樹會變成半透明切片。這時候半透明區域會將後面的地形隱藏掉。
現在時候很容易解釋這個問題了。借用LearnOpenGL作者的圖:
看籃圈的部分:
如果先繪製前面的圖,由於Z-Buffer是不理會Alpha的,所以,這裏的透明像素也會被寫進ZBuffer。
當繪製後面的物體時(無論它是不是透明,只要他比前面物體遠)Z-測試會失敗,然後對應像素就被丟棄了。
結論:Z-Buffer和Blending一起用的時候,必須先畫遠處物件再畫近處的,才能保證不出錯。
那麼之前用的樹木,即便可以排序,每幀將幾千棵樹每幀排一次序,然後在渲染,也是非常恐怖的開銷,所以索性直接換成SpeedTree好了,直接用模型LOD,也不是用貼圖LOD,雖然它確實很省。
方法:如何正確使用Blending。
- 先繪製所有不透明的物體。
- 對所有透明的物體排序。
- 按順序(由遠到進)繪製所有透明的物體。具體來講,可以按距離插入排序,先畫遠處,後畫近處。