天天看點

PBR 與 OpenGL ES 2.0 中的LOD紋理:Mipmap (關于Lod和Bias)MipMapLOD實作的原理實際使用

MipMap

當使用Mipmap的時候可能會用到

xxxLod

xxxBias

這幾種紋理采樣函數。

在片段着色器中:

    • vec4 texture2D (sampler2D sampler, vec2 coord )

    • vec4 textureCube (samplerCube sampler,vec3 coord )

      自動計算使用的紋理層。
    • vec4 texture2D (sampler2D sampler, vec2 coord, float bias)

    • vec4 textureCube (samplerCube sampler, vec3 coord, float bias )

      需要在t.w中指定一個偏移量來把自動計算出的紋理層全部偏移指定的值。
    • vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod)

    • vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod)

      需要在t.w中明确指定要使用的紋理層。

下面一段話出自Unity3D的論壇,都是互通的:

In the PS the LOD is determined from the derivatives of the texCoords automatically(tex2D). You can also specify the derivatives explicitly as two extra arguments

tex2D(textureMap, texCoord, ddx(texCoord), ddy(texCoord))

is equivalent to your tex2D, though of course you could use something else as the derivative.

Alternately, you can use tex2Dlod to explicitly select the LOD speicifed by the ‘w’ component of texCoord; eg, something like:

tex2Dlod(textureMap, float4(texCoord.xy, 0, lod))

LOD實作的原理

首先明确幾個概念:

  1. 螢幕上的顔色點叫像素,紋理上的顔色點叫紋素。
  2. 螢幕坐标系我們用XY坐标系,紋理坐标系用UV坐标系。
  3. GPU在着色器階段是在螢幕空間XY坐标系中對每一個像素去對應的紋理中查找對應的紋素來确定像素的顔色。

即在着色階段是一個XY空間到UV空間的映射。

我們可以分别求x和y偏導數,通過X和Y的偏導數中的較大值作為螢幕單個像素寬度紋理坐标的變化率。

在Shader中使用

tex2D(tex, uv)

的時候相當于在GPU内部展開成下面:

tex2D(sampler2D tex, float4 uv)
{
    float lod = CalcLod(ddx(uv), ddy(uv));
    uv.w= lod;
    return tex2Dlod(tex, uv);
}
           

至此uv已經是個(xyzw)的向量,但是并不能确定使用第幾層的MipMap,計算LOD的原理函數代碼如下:

float mipmapLevel(float2 uv, float2 textureSize)
{
    float dx = ddx(uv * textureSize.x);
    float dy = ddy(uv * textureSize.y);
    float d = max(dot(dx, dx), dot(dy, dy));  
    return  * log2(d);//0.5是技巧,本來是d的平方。
} 
           

實際使用

在PBR渲染中,在算物體表面反射的時候,可以使用Texture自帶的MIPMAP來模拟粗糙的效果,簡化積分的計算。

順便推薦幾個學習PBR的網站:

- 微軟大牛叛逆者

- LearnOpenGL

繼續閱讀