如何将多个纹理应用于每个对象的不同面?
特别是我画了一个立方体:
我希望能够在立方体的每个不同面上绘制不同的图像(或子图像)。我该怎么做?
顶点着色器:
#version 330 core
uniform vec3 position = vec3(0.0, 0.0, 0.0);
void main() {
gl_Position = vec4(position, 1.0);
}
几何着色器:
#version 330 core
layout(points) in;
layout(triangle_strip, max_vertices=64) out;
out vec2 tex_coord;
uniform mat4x4 model;
uniform mat4x4 view;
uniform mat4x4 projection;
uniform float size = 1.0;
const vec2 texc[4] = vec2[](vec2(0, 0), // texture coordinates
vec2(1, 0),
vec2(0, 1),
vec2(1, 1));
void main() {
float asize = size / 2;
vec4 offset[24] = vec4[] (
vec4(-asize, asize, -asize, 0.0), //top face
vec4( asize, asize, -asize, 0.0),
vec4(-asize, asize, asize, 0.0),
vec4( asize, asize, asize, 0.0),
vec4(-asize, -asize, -asize, 0.0), //bottom face
vec4( asize, -asize, asize, 0.0),
vec4(-asize, -asize, -asize, 0.0),
vec4( asize, -asize, asize, 0.0),
vec4(-asize, asize, -asize, 0.0), //left face
vec4(-asize, asize, asize, 0.0),
vec4(-asize, -asize, -asize, 0.0),
vec4(-asize, -asize, asize, 0.0),
vec4( asize, asize, -asize, 0.0), //right face
vec4( asize, asize, asize, 0.0),
vec4( asize, -asize, -asize, 0.0),
vec4( asize, -asize, asize, 0.0),
vec4(-asize, asize, asize, 0.0), //rear face
vec4( asize, asize, asize, 0.0),
vec4(-asize, -asize, asize, 0.0),
vec4( asize, -asize, asize, 0.0),
vec4(-asize, asize, -asize, 0.0), //front face
vec4( asize, asize, -asize, 0.0),
vec4(-asize, -asize, -asize, 0.0),
vec4( asize, -asize, -asize, 0.0));
int i, j, k;
for(i = 0; i < gl_in.length(); ++i) { // for each input vertex generate a cube
for(k = 0; k < offset.length() / 4; ++k) { // for each face of the cube
for(j = 0; j < 4; ++j) { // for each vertex per face
gl_Position = projection * view * model * (gl_in[i].gl_Position + offset[j + k*4]);
tex_coord = texc[j];
EmitVertex();
}
EndPrimitive();
}
}
}
片段着色器:
#version 330 core
out vec4 fragment_out;
uniform sampler2D tex;
in vec2 tex_coord;
void main() {
fragment_out = texture(tex, tex_coord);
}
答案 0 :(得分:2)
这是您可以采用的最简单方法,因为您有一个几何着色器:
#version 330 core
layout(points) in;
layout(triangle_strip, max_vertices=64) out;
out vec2 tex_coord;
uniform mat4x4 model;
uniform mat4x4 view;
uniform mat4x4 projection;
uniform float size = 1.0;
const vec2 texc[4] = vec2[](vec2(0, 0), // texture coordinates
vec2(1, 0),
vec2(0, 1),
vec2(1, 1));
void main() {
float asize = size / 2;
vec4 offset[24] = vec4[] (
vec4(-asize, asize, -asize, 0.0), //top face
vec4( asize, asize, -asize, 0.0),
vec4(-asize, asize, asize, 0.0),
vec4( asize, asize, asize, 0.0),
vec4(-asize, -asize, -asize, 0.0), //bottom face
vec4( asize, -asize, asize, 0.0),
vec4(-asize, -asize, -asize, 0.0),
vec4( asize, -asize, asize, 0.0),
vec4(-asize, asize, -asize, 0.0), //left face
vec4(-asize, asize, asize, 0.0),
vec4(-asize, -asize, -asize, 0.0),
vec4(-asize, -asize, asize, 0.0),
vec4( asize, asize, -asize, 0.0), //right face
vec4( asize, asize, asize, 0.0),
vec4( asize, -asize, -asize, 0.0),
vec4( asize, -asize, asize, 0.0),
vec4(-asize, asize, asize, 0.0), //rear face
vec4( asize, asize, asize, 0.0),
vec4(-asize, -asize, asize, 0.0),
vec4( asize, -asize, asize, 0.0),
vec4(-asize, asize, -asize, 0.0), //front face
vec4( asize, asize, -asize, 0.0),
vec4(-asize, -asize, -asize, 0.0),
vec4( asize, -asize, -asize, 0.0));
int i, j, k;
for(i = 0; i < gl_in.length(); ++i) { // for each input vertex generate a cube
for(k = 0; k < offset.length() / 4; ++k) { // for each face of the cube
gl_PrimitiveID = k; // Must set this, otherwise it will be undefined in the FS
for(j = 0; j < 4; ++j) { // for each vertex per face
gl_Position = projection * view * model * (gl_in[i].gl_Position + offset[j + k*4]);
tex_coord = texc[j];
EmitVertex();
}
EndPrimitive();
}
}
}
#version 330 core
out vec4 fragment_out;
uniform sampler2D tex [6];
in vec2 tex_coord;
void main() {
fragment_out = texture (tex [gl_PrimitiveID], tex_coord);
}
现在,只需设置6个不同的纹理图像单元即可完成。
注意:您必须在几何着色器中编写gl_PrimitiveID
,否则它将在片段着色器中未定义。因此GS中还有1行,通常GL会自动为您生成此值。
答案 1 :(得分:1)
首先你需要将两个纹理单元传递给着色器,并以某种方式调制或添加它们,例如:
#version 330 core
out vec4 fragment_out;
uniform sampler2D tex;
uniform sampler2D tex2;
in vec2 tex_coord;
void main() {
fragment_out = texture(tex, tex_coord)*texture(tex2, tex_coord);
}
不幸的是,通过这种方式,您将为同一面具有2个纹理。如果你想要每面纹理。
- 您可以拥有多个纹理坐标,并在着色器中将每个纹理与一组texcoords一起使用,因此您可以使用另一个tex_coord
而不是tex_coord2
。
#version 330 core
out vec4 fragment_out;
uniform sampler2D tex;
uniform sampler2D tex2;
in vec2 tex_coord;
in vec2 tex_coord;
void main() {
fragment_out = texture(tex, tex_coord) + texture(tex2, tex_coord2);
}
- 另一种方法是将多个图像组合在一个图像中并使其下以使每个面具有大图像的单独部分。
- 更简单的方法是将每张脸作为一个单独的对象处理,但这是非常不推荐的。