我需要将一个立方体贴图的特定面渲染到四边形以进行调试。
从this类似的问题我收集你使用三维纹理坐标,但我需要一些信息来克服这个障碍。我现在得到的只是黑色,有时完全是不同的颜色。
到目前为止,我已经使用以下内容绘制了2D四边形。
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, textureID);
GL.BindVertexArray(VAO);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length);
我需要在这里进行调整吗?这样做的一般方法是什么?
答案 0 :(得分:2)
需要进行一些更改,这些更改都非常简单。
您当前使用TextureTarget.Texture2D
的位置,您将使用TextureTarget.TextureCubeMap
。例如,假设您已经有一个给定的立方体贴图纹理:
GL.BindTexture(TextureTarget.TextureCubeMap, textureID);
在片段着色器中,您当前定义了一个采样器变量,它看起来像这样:
uniform sampler2D Tex;
您将修改为:
uniform samplerCube Tex;
最大的变化与纹理坐标有关。用于立方体贴图的纹理坐标将具有3个组件,可以将其解释为方向向量。想象与以原点为中心的立方体贴图对应的立方体。然后,纹理坐标给出的方向向量指向将要采样的纹素。
一个选项是修改客户端代码生成的顶点属性中的纹理坐标。您可以将它们扩展为3个组件而不是之前的2个组件,并选择适当的值来隔离要渲染的面。
根据您已经传递给2D纹理的着色器代码的现有纹理坐标,计算新纹理坐标可能更容易。当前纹理坐标在两个坐标方向上跨越范围[0.0,1.0]的正方形时,您需要将该范围映射到多维数据集的面,其中多维数据集以原点为中心,并且具有范围[-1.0,1.0 ]在每个坐标方向上。
要完成此操作,请使用-1.0或1.0作为与要隔离的面匹配的坐标方向,并将输入纹理坐标从范围[0.0,1.0]缩放/移位到范围[-1.0,1.0]其他两个坐标方向。
假设您在2D纹理案例的着色器代码中有以下内容:
uniform sampler2D Tex;
in vec2 TexCoord;
...
vec4 val = texture(Tex, TexCoord);
然后,对于GL_TEXTURE_CUBE_MAP_POSITIVE_X
面,使用1.0作为立方体纹理坐标的x坐标,并缩放/移动剩余的两个坐标:
uniform samplerCube Tex;
in vec2 TexCoord;
...
vec2 mapCoord = 2.0 * TexCoord - 1.0;
vec4 val = texture(Tex, vec3(1.0, mapCoord.xy));
等同于GL_TEXTURE_CUBE_MAP_NEGATIVE_X
face:
vec4 val = texture(Tex, vec3(-1.0, mapCoord.xy));
对于GL_TEXTURE_CUBE_MAP_POSITIVE_Y
脸:
vec4 val = texture(Tex, vec3(mapCoord.x, 1.0, mapCoord.y));
对于GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
脸:
vec4 val = texture(Tex, vec3(mapCoord.x, -1.0, mapCoord.y));
对于GL_TEXTURE_CUBE_MAP_POSITIVE_Z
脸:
vec4 val = texture(Tex, vec3(mapCoord.xy, 1.0));
对于GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
脸:
vec4 val = texture(Tex, vec3(mapCoord.xy, -1.0));
请注意,立方体贴图面的方向有点模糊。如果您对结果输出的方向有特定的期望,则可能必须置换/镜像上面代码中的某些值。
答案 1 :(得分:0)
在上面Reto的答案的基础上,我想到了以下(伪)代码,用于将立方体贴图的给定面呈现为具有正确方向的四边形。
示例四边形生成器(C):
typedef struct {
vec3 position;
vec2 uv;
} shader_quads_vertex;
typedef struct {
shader_quads_vertex verts[6];
} vert_quad;
// ...
// Don't forget to set vertex attributes correctly
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
sizeof(shader_quads_vertex), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
sizeof(shader_quads_vertex), (void *)sizeof(vec3));
// ...
// v3 *----* v2
// | |
// v0 *----* v1
//
// v0, v1, v2, v0, v2, v3
vert_quad quad = { 0 };
quad.verts[0].position.x = x0; // v0 (0,0)
quad.verts[0].position.y = y0;
quad.verts[0].uv.u = 0.0f;
quad.verts[0].uv.v = 0.0f;
quad.verts[1].position.x = x1; // v1 (1,0)
quad.verts[1].position.y = y0;
quad.verts[1].uv.u = 1.0f;
quad.verts[1].uv.v = 0.0f;
quad.verts[2].position.x = x1; // v2 (1,1)
quad.verts[2].position.y = y1;
quad.verts[2].uv.u = 1.0f;
quad.verts[2].uv.v = 1.0f;
quad.verts[3].position.x = x0; // v0 (0,0)
quad.verts[3].position.y = y0;
quad.verts[3].uv.u = 0.0f;
quad.verts[3].uv.v = 0.0f;
quad.verts[4].position.x = x1; // v2 (1,1)
quad.verts[4].position.y = y1;
quad.verts[4].uv.u = 1.0f;
quad.verts[4].uv.v = 1.0f;
quad.verts[5].position.x = x0; // v3 (0,1)
quad.verts[5].position.y = y1;
quad.verts[5].uv.u = 0.0f;
quad.verts[5].uv.v = 1.0f;
// TODO: Bind shader, set uniforms, push quad into your vertex buffer
//glBindBuffer(GL_ARRAY_BUFFER, ...);
//glBufferData(...)
// TODO: Draw 1 face, or 6 faces, or whatever you like. E.g. draw 6 faces:
//for (int face = 0; face < 6; face++) {
// TODO: Set "u_face" to face index via uniform via glUniform1i()
// glDrawArrays(GL_TRIANGLES, 0, 6);
//}
顶点着色器(GLSL):
#version 330 core
layout(location = 0) in vec3 attr_position;
layout(location = 1) in vec2 attr_uv;
uniform int u_face;
out vs_out {
vec3 uvw;
} vertex;
void main()
{
gl_Position = vec4(attr_position, 1.0);
vec2 uv_cube = attr_uv.xy * 2.0 - 1.0;
switch (u_face) {
case 0:
vertex.uvw = vec3(1.0, uv_cube.y, uv_cube.x);
break;
case 1:
vertex.uvw = vec3(-1.0, uv_cube.y, -uv_cube.x);
break;
case 2:
vertex.uvw = vec3(uv_cube.x, 1.0, uv_cube.y);
break;
case 3:
vertex.uvw = vec3(uv_cube.x, -1.0, -uv_cube.y);
break;
case 4:
vertex.uvw = vec3(-uv_cube.x, uv_cube.y, 1.0);
break;
case 5:
vertex.uvw = vec3(uv_cube.x, uv_cube.y, -1.0);
break;
};
}
碎片着色器(GLSL):
#version 330 core
in vs_out {
vec3 uvw;
} vertex;
uniform samplerCube u_tex;
out vec4 final_color;
void main()
{
vec4 tex_color = texture(u_tex, vertex.uvw);
final_color = vec4(vec3(tex_color.r), 1.0);
}
注意:上面的代码对您的坐标系做出了以下假设:
我确实测试了此代码,但是为了简洁起见,我省略了许多样板代码GL代码。希望对您有所帮助。