Deferred rendering Gbuffer優化: 單張Float16紋理存儲更多信息來"模擬"MRT

請見Demo:http://www.artvily.com/renderCase?sample=oneFloatTexToMRT

光照在 Deferred rendering 機制下性能會更好, 尤其是基於tile base rendering 或者 cluster rendering 的光照數據檢索原理,會讓性能更優。但是gbuffer在使用的時候,一般都需要硬件對MRT的支持, 即使支持MRT也都希望在單張紋理裏面放入更多的數據。這裏給的樣例就是在單張 float16數據格式的紋理中放入: Normal, RGB, Position。有了這三類數據,就能做延遲光照了。例如移動端這種對性能帶寬要求更加苛刻的設備上,這個方式可能會很有價值。例如在只支持webgl1(gles2)的設備上完成Deferred Rendering。

注意,雖然這裏的法線損精度降低,但是基本夠用。

上圖的整個有半部分, 展示的是延遲光照的渲染結果。左下部分是法線,左上部分是原始的紋理RGB展示。

gbuffer 片段着色器代碼,展示如何將對應數據塞入到 float16格式的浮點數中(這一點非常重要,要注意取值範圍和浮點數的存儲方式)

// gbuffer fragment shader

vec4 color0 = texture(u_sampler0,v_texUV.xy);
vec3 color = floor(color0.rgb * 90.0) * 0.1;
vec3 floor_pnv = floor(98.0 * v_pnvs) * 10.0;
vec3 tnv = floor_pnv + vec3(0.00001);
floor_pnv += (tnv / abs(tnv)) * color;
OutputColor = vec4(floor_pnv, v_viewZ);
// 這個v_viewZ 指的是片段對應的攝像機空間的位置到攝像機座標原點的距離

使用gbuffer 紋理數據得到 Normal, RGB, Camera View Space Position 的fragment shader 的代碼:

// 獲得 Camera View Space Position的函數
vec3 clacViewPosFromSPosAndVZ(vec2 screenPos, float viewZ)
{
    vec3 mpnv = vec3(screenPos.x * u_frustumParam.z,screenPos.y * u_frustumParam.w,u_frustumParam.x);
    mpnv = normalize(mpnv);
    mpnv = mpnv * (viewZ / mpnv.z);
    return mpnv;
}

// 還原 Normal, RGB, View Space Position
// v_texUV(取值範圍爲: 0.0->1.0)
vec4 baseColor = texture(u_sampler0,v_texUV.xy);
vec3 geomRGB = abs(baseColor.rgb);
geomRGB = u_color.a * fract(geomRGB* 0.1) / 0.9;
vec3 nv = floor(baseColor.rgb * 0.1);
nv = nv / 98.0;
nv = normalize(nv);
vec2 screenPos = (v_texUV - 0.5 ) / vec2(0.5,0.5);
vec3 viewSpacePos = clacViewPosFromSPosAndVZ(screenPos, baseColor.a);

 

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