使用 OpenGL 在立方体面上重复立方体贴图纹理
Repeat a cubemap texture on a cube face with OpenGL
是否可以使用 OpenGL 在给定的面上重复立方体贴图纹理(GL_TEXTURE_CUBE_MAP_POSITIVE_X...)?
我有一个简单的单位立方体,它有 24 个以原点为中心的顶点(xyz 在 (-0.5, -0.5, -0.5) 和 (0.5, 0.5, 0.5) 之间)。在其属性中,最初我将 uvw 坐标设置为片段着色器中的 xyz 位置,就像在立方体贴图中所做的那样 learnopengl.com tutorial。我显然也尝试过将单独的 uvw 坐标设置为等于比例的值,但是纹理没有在任何立方体面上重复,如下图所示(我在片段着色器中绘制了 uvw 坐标):
height(顶部像素的 y 坐标)= 上图中的 3.5,因此通过为顶部的顶点设置 v = 3.5,我希望渐变垂直重复(事实并非如此) .
如果这不可能,我剩下的唯一修复方法就是在每个顶点上分配一个带有自定义 uv 坐标的 2D 纹理,对吗?
不,立方体贴图无法使用 GL_REPEAT
环绕。 您可能应该看看人们在评论中建议的替代方案。
这样做的原因是,您传递给立方体贴图采样器的坐标被解释为一个方向。这个方向的长度被忽略。你可以把它想象成用于采样的 vec3 被归一化了——因此,包装永远不会发生。
如果出于任何原因需要使用立方体贴图,可以在着色器中修改采样方向。
vec3 tweakSampleDirForReapeat(vec3 dir, float repeatScale)
{
for(int i = 0; i < 3; i++) {
float d = abs(dir[i]);
if(abs(d) >= 0.5) // skip dominant direction (assuming a coordinate in a unit cube centered at the origin)
continue;
d += 0.5; // transform from [-0.5, +0.5] range to [0, 1]
d *= repeatScale; // transform from [0, 1] range to [0, repeatScale]
d = fract(d); // wrap [0, repeatScale] to multiple [0, 1] ranges
d -= 0.5; // transform from [0, 1] range to [-0.5, +0.5]
dir[i] = d;
}
return dir;
}
免责声明:这段代码应该可以工作,但我还没有真正尝试过。
可以调整此代码以支持每个面的不同 repearScales。
编辑:
我将尝试解释这段代码的作用。
假设我们有一个点位于立方体的 +X 面上。
我们正在尝试修改这个蓝点的位置。我们还不知道把这个点放在哪里。但是这个点会在同一张脸
在这种情况下,X 值等于 +0.5。其他坐标(Y 和 Z)的绝对值将小于 0.5。
这就是我们要检查的内容,如果:
if(abs(d) >= 0.5) // skip dominant direction
continue;
所以基本上,如果 X 是 -0.5 或 +0.5,我们不想更改 X,以使其保持在同一面上。
我们只会修改 Y 和 Z。
现在让我们从不同的角度来看立方体。现在我们看到 +X 面朝我们了。
从这个角度我们可以清楚地看到 Y 和 Z 都 < 0.5(绝对值),因为点在框内。
现在让我们引入纹理。
默认情况下,我们会将整个纹理溅到脸上。
但我们想要这样的东西。
这就是此转换试图做的事情:
d += 0.5; // transform from [-0.5, +0.5] range to [0, 1]
d *= repeatScale; // transform from [0, 1] range to [0, repeatScale]
d = fract(d); // wrap [0, repeatScale] to multiple [0, 1] ranges
d -= 0.5; // transform from [0, 1] range to [-0.5, +0.5]
我建议您使用纸和铅笔通过几个示例来完成该算法。我相信你最终会理解它,这只是投入一些时间的问题。祝你好运!
测验问题:上一张图片的“repeatScale”是多少?
是否可以使用 OpenGL 在给定的面上重复立方体贴图纹理(GL_TEXTURE_CUBE_MAP_POSITIVE_X...)?
我有一个简单的单位立方体,它有 24 个以原点为中心的顶点(xyz 在 (-0.5, -0.5, -0.5) 和 (0.5, 0.5, 0.5) 之间)。在其属性中,最初我将 uvw 坐标设置为片段着色器中的 xyz 位置,就像在立方体贴图中所做的那样 learnopengl.com tutorial。我显然也尝试过将单独的 uvw 坐标设置为等于比例的值,但是纹理没有在任何立方体面上重复,如下图所示(我在片段着色器中绘制了 uvw 坐标):
height(顶部像素的 y 坐标)= 上图中的 3.5,因此通过为顶部的顶点设置 v = 3.5,我希望渐变垂直重复(事实并非如此) .
如果这不可能,我剩下的唯一修复方法就是在每个顶点上分配一个带有自定义 uv 坐标的 2D 纹理,对吗?
不,立方体贴图无法使用 GL_REPEAT
环绕。 您可能应该看看人们在评论中建议的替代方案。
这样做的原因是,您传递给立方体贴图采样器的坐标被解释为一个方向。这个方向的长度被忽略。你可以把它想象成用于采样的 vec3 被归一化了——因此,包装永远不会发生。
如果出于任何原因需要使用立方体贴图,可以在着色器中修改采样方向。
vec3 tweakSampleDirForReapeat(vec3 dir, float repeatScale)
{
for(int i = 0; i < 3; i++) {
float d = abs(dir[i]);
if(abs(d) >= 0.5) // skip dominant direction (assuming a coordinate in a unit cube centered at the origin)
continue;
d += 0.5; // transform from [-0.5, +0.5] range to [0, 1]
d *= repeatScale; // transform from [0, 1] range to [0, repeatScale]
d = fract(d); // wrap [0, repeatScale] to multiple [0, 1] ranges
d -= 0.5; // transform from [0, 1] range to [-0.5, +0.5]
dir[i] = d;
}
return dir;
}
免责声明:这段代码应该可以工作,但我还没有真正尝试过。
可以调整此代码以支持每个面的不同 repearScales。
编辑: 我将尝试解释这段代码的作用。
假设我们有一个点位于立方体的 +X 面上。
我们正在尝试修改这个蓝点的位置。我们还不知道把这个点放在哪里。但是这个点会在同一张脸
在这种情况下,X 值等于 +0.5。其他坐标(Y 和 Z)的绝对值将小于 0.5。
这就是我们要检查的内容,如果:
if(abs(d) >= 0.5) // skip dominant direction
continue;
所以基本上,如果 X 是 -0.5 或 +0.5,我们不想更改 X,以使其保持在同一面上。
我们只会修改 Y 和 Z。
现在让我们从不同的角度来看立方体。现在我们看到 +X 面朝我们了。
从这个角度我们可以清楚地看到 Y 和 Z 都 < 0.5(绝对值),因为点在框内。
现在让我们引入纹理。
默认情况下,我们会将整个纹理溅到脸上。
但我们想要这样的东西。
这就是此转换试图做的事情:
d += 0.5; // transform from [-0.5, +0.5] range to [0, 1]
d *= repeatScale; // transform from [0, 1] range to [0, repeatScale]
d = fract(d); // wrap [0, repeatScale] to multiple [0, 1] ranges
d -= 0.5; // transform from [0, 1] range to [-0.5, +0.5]
我建议您使用纸和铅笔通过几个示例来完成该算法。我相信你最终会理解它,这只是投入一些时间的问题。祝你好运!
测验问题:上一张图片的“repeatScale”是多少?