为何GLSL中使用1.0/textureSize计算单个texel的尺寸?
为什么使用
1.0 / textureSize(image, 0)计算单个纹素(texel)尺寸 你的推导逻辑完全正确,这个公式的成立前提是OpenGL的纹理采样规则:所有纹理的UV坐标都是归一化的[0.0, 1.0]区间值,和纹理本身的实际像素分辨率无关。
具体逻辑拆解
- GLSL内置函数
textureSize(sampler, lod)会返回指定LOD层级下纹理的实际像素分辨率,比如一张分辨率为1024×512的纹理,调用textureSize(image, 0)(0代表基础LOD层)会返回ivec2(1024, 512) - 归一化规则下,纹理的完整宽度对应UV坐标的1.0单位,这个范围内总共排布了1024个横向纹素,因此单个横向纹素对应的UV偏移量就是
1.0 / 1024 - 同理单个纵向纹素对应的UV偏移量是
1.0 / 512 - 把两个维度的计算合并就得到了代码里的写法:
vec2 tex_offset = 1.0 / textureSize(image, 0);
计算得到的tex_offset本质是单个纹素在归一化UV坐标系下的尺寸,方便我们在着色器中精准对相邻纹素做采样。你贴的高斯模糊代码就是典型的使用场景:
#version 330 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D image; uniform bool horizontal; uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); void main() { vec2 tex_offset = 1.0 / textureSize(image, 0); // 获取单个纹素的UV尺寸 vec3 result = texture(image, TexCoords).rgb * weight[0]; // 当前片段的贡献值 if(horizontal) { for(int i = 1; i < 5; ++i) { // 水平方向左右偏移i个纹素采样 result += texture(image, TexCoords + vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; result += texture(image, TexCoords - vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; } } else { for(int i = 1; i < 5; ++i) { // 垂直方向上下偏移i个纹素采样 result += texture(image, TexCoords + vec2(0.0, tex_offset.y * i)).rgb * weight[i]; result += texture(image, TexCoords - vec2(0.0, tex_offset.y * i)).rgb * weight[i]; } } FragColor = vec4(result, 1.0); }
这段代码实现了可分离的高斯模糊,将二维高斯卷积拆分为水平、垂直两个一维卷积Pass,每次采样偏移时乘以tex_offset就能保证每次偏移刚好对应一个实际纹素的位置,保证模糊效果的准确性。
内容的提问来源于stack exchange,提问作者San Andreas
相关产品推荐
相关产品推荐

