PBR 与 OpenGL ES 2.0 中的LOD纹理:Mipmap (关于Lod和Bias)

MipMap

当使用Mipmap的时候可能会用到xxxLodxxxBias 这几种纹理采样函数。

片段着色器中:

    • 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 0.5 * log2(d);//0.5是技巧,本来是d的平方。
} 

实际使用

在PBR渲染中,在算物体表面反射的时候,可以使用Texture自带的MIPMAP来模拟粗糙的效果,简化积分的计算。

顺便推荐几个学习PBR的网站:
- 微软大牛叛逆者
- LearnOpenGL

你可能感兴趣的:(OpenGL)