在着色器中的平铺纹理

时间:2011-06-24 20:18:05

标签: glsl textures shader

我传递给顶点着色器(glsl)2个纹理:从屏幕和较小的法线贴图。 Normalmap按屏幕大小缩放。因此,如果第一个纹理是1152×864像素而法线贴图是256×256,那么它将从它的大小缩放到更大。

如何让它平铺?例如。将其大小设为256×256并平铺所有纹理。


UPD

例如,我的主(大)纹理映射如下:

[0.17, 0.61, 0.33, 0.83]

而不是:

[0, 0, 1, 1]

这样我的普通纹理也会映射到第一个坐标。所以我看到了一个小的映射矩形。如何在着色器中将其映射为完整尺寸?

1 个答案:

答案 0 :(得分:6)

  

它将从它的大小缩放到更大。

不,它肯定不会。这是对纹理的常见误解。纹理只不过是花哨的查找表。纹理不是相对于彼此“缩放”的;它只是你使用什么纹理坐标的问题。

很可能,你正在做的是使用与普通地图相同的纹理坐标作为屏幕纹理。由于我们可能正在讨论规范化纹理坐标,这意味着您将相同的[0,1]范围映射到它们两者。

要获得您正在谈论的效果,您需要计算正常纹理的纹理坐标,以满足您的需要。因此,如果您具有相对于屏幕纹理的纹理坐标,则必须将其转换为您想要的空间以用于普通纹理。

有几种方法可以做到这一点。手动方式是在CPU上计算纹理大小的比例,然后将其传递给着色器。使用您给出的数字,大小比率为:

(1152.0/256.0, 864.0/256.0) = (4.5, 3.375).

确保这是在浮点数学中完成的。完成后,只需将其传递给均匀,然后在采样前将纹理坐标乘以着色器中的此比率:

uniform vec2 textureRatio;

void main() {
//Get the texture coordinate.
vec4 screenTexColor = texture(screenTex, texCoord);
vec2 normTexCoord = textureRatio * texCoord;
vec4 normalValue = texture(normalTex, normTexCoord);
//Do something with these.
}

GLSL中的自动方式是直接在着色器中执行此操作。这需要GLSL 1.30或更高。基本上,您使用该语言的可用功能来计算比率:

void main() {
//Get the texture coordinate.
vec2 textureRatio = textureSize(screenTex) / textureSize(normalTex);
vec4 screenTexColor = texture(screenTex, texCoord);
vec2 normTexCoord = textureRatio * texCoord;
vec4 normalValue = texture(normalTex, normTexCoord);
//Do something with these.
}

在这两种情况下,我假设您的GL_TEXTURE_WRAP_S / T设置为GL_REPEAT,并带有适当的纹理或采样器参数。

请注意,计算CPU上的比率并将其作为统一传递可能比在着色器中计算它更快。特别是片段着色器,它将运行非常多。