纹理被渲染为黑色四边形
Texture being rendered as black quad
我一直在尝试遵循 code as specified in this tutorial on OpenGL3+ textures,但我的结果最终是黑色而不是纹理。
我正在使用 stbimage 将纹理使用的图像加载到直接的 ByteBuffer 中,并且可以保证缓冲区中的 RGB 数据至少是不统一的 - 所以不可能是那样。
我通常不喜欢转储代码,但目前我看不出还有什么可以做的。这是我的 java 代码和着色器:
GL
是指向LWJGL31.
中所有GL##功能的接口
ShaderProgram
将所有特定于着色器的内容包装到一个漂亮的黑盒中,该黑盒在第一次调用 use(GL)
时从附加的着色器生成一个着色器程序,然后重用该程序。这适用于渲染彩色三角形,所以我排除了其中的任何错误。
Util.checkError(GL, boolean);
会检查自上次执行以来累积的任何 OpenGL 错误,如果未设置布尔值则抛出 运行time 异常(如果设置则静默写入日志) .
渲染代码,update(GL, long)是运行每帧一次
private static final ResourceAPI res = API.get(ResourceAPI.class);
Image lwjgl32;
ShaderProgram prog = new ShaderProgram();
int vbo, vao, ebo;
int texture;
@Override
public void init(GL gl) {
try {
prog.attach(res.get("shaders/texDemo.vert", ShaderSource.class));
prog.attach(res.get("shaders/texDemo.frag", ShaderSource.class));
lwjgl32 = res.get("textures/lwjgl32.png", Image.class);
} catch(ResourceException e) {
throw new RuntimeException(e);
}
float[] vertices = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
int[] indices = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
vao = gl.glGenVertexArrays();
vbo = gl.glGenBuffers();
ebo = gl.glGenBuffers();
gl.glBindVertexArray(vao);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo);
gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, ebo);
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices, GL.GL_STATIC_DRAW);
gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 0);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 3 * Float.BYTES);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(2, 2, GL.GL_FLOAT, false, 8 * Float.BYTES, 6 * Float.BYTES);
gl.glEnableVertexAttribArray(0);
texture = gl.glGenTextures();
gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8, lwjgl32.getWidth(), lwjgl32.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, lwjgl32.getImageData());
gl.glGenerateMipmap(GL.GL_TEXTURE_2D);
prog.use(gl);
gl.glUniform1i(gl.glGetUniformLocation(prog.getId(gl), "texture"), 0);
Util.checkError(gl, false);
}
@Override
protected void update(GL gl, long deltaFrame) {
gl.glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
prog.use(gl);
gl.glBindVertexArray(vao);
gl.glDrawElements(GL.GL_TRIANGLES, 6, GL.GL_UNSIGNED_INT, 0);
}
@Override
public void clean(GL gl) {
gl.glDeleteVertexArrays(vao);
gl.glDeleteBuffers(vbo);
gl.glDeleteBuffers(ebo);
ShaderProgram.clearUse(gl);
prog.dispose(gl);
}
顶点着色器
#version 330 core
layout (location = 0) in vec3 in_position;
layout (location = 1) in vec3 in_color;
layout (location = 2) in vec2 in_texCoord;
out vec3 color;
out vec2 texCoord;
void main() {
gl_Position = vec4(in_position, 1.0);
color = in_color;
texCoord = vec2(in_texCoord.x, in_texCoord.y);
}
片段着色器
#version 330 core
out vec4 frag_colour;
in vec3 color;
in vec2 texCoord;
uniform sampler2D texture;
void main() {
frag_colour = texture(texture, texCoord) * vec4(color, 1.0);
}
1我将 LWJGL3 的 GL## static 类 包装到单个接口和实现中,这样我就可以拥有一堆有状态的方法例如识别正在呈现的上下文等。我也尽力从界面中删除非核心功能,所以我什至不想使用已弃用的东西
仅看代码很难判断,但黑色四边形表示片段着色器中的这一行:
frag_colour = texture(texture, texCoord) * vec4(color, 1.0);
评估为 0。这意味着纹理不正确 read/bound,您的纹理坐标关闭或颜色为零向量。确保您的纹理图像已正确加载(文件存在,具有宽度和高度等)并且具有正确的格式。我通常调试着色器的做法是将每个参数设置为颜色,以在其具有正确的值时给出提示:
frag_colour = vec4(color, 1.0); //Makes sure the color is right
或
frag_colour = texture(texture, texCoord); //Makes sure the texture is loaded and bound
如果这还不能提供足够的信息,请提供更多详细信息:
frag_colour = vec4(color.x, color.x, color.x, 1.0);
或
frag_colour = vec4(texCoord.x, texCoord.x, texCoord.x, 1.0);
你只启用索引为0的顶点属性,但是这3次。
像这样调整您的代码:
gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 0);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 3 * Float.BYTES);
gl.glEnableVertexAttribArray(1); // <-------
gl.glVertexAttribPointer(2, 2, GL.GL_FLOAT, false, 8 * Float.BYTES, 6 * Float.BYTES);
gl.glEnableVertexAttribArray(2); // <------
我一直在尝试遵循 code as specified in this tutorial on OpenGL3+ textures,但我的结果最终是黑色而不是纹理。
我正在使用 stbimage 将纹理使用的图像加载到直接的 ByteBuffer 中,并且可以保证缓冲区中的 RGB 数据至少是不统一的 - 所以不可能是那样。
我通常不喜欢转储代码,但目前我看不出还有什么可以做的。这是我的 java 代码和着色器:
GL
是指向LWJGL31.
ShaderProgram
将所有特定于着色器的内容包装到一个漂亮的黑盒中,该黑盒在第一次调用 use(GL)
时从附加的着色器生成一个着色器程序,然后重用该程序。这适用于渲染彩色三角形,所以我排除了其中的任何错误。
Util.checkError(GL, boolean);
会检查自上次执行以来累积的任何 OpenGL 错误,如果未设置布尔值则抛出 运行time 异常(如果设置则静默写入日志) .
渲染代码,update(GL, long)是运行每帧一次
private static final ResourceAPI res = API.get(ResourceAPI.class);
Image lwjgl32;
ShaderProgram prog = new ShaderProgram();
int vbo, vao, ebo;
int texture;
@Override
public void init(GL gl) {
try {
prog.attach(res.get("shaders/texDemo.vert", ShaderSource.class));
prog.attach(res.get("shaders/texDemo.frag", ShaderSource.class));
lwjgl32 = res.get("textures/lwjgl32.png", Image.class);
} catch(ResourceException e) {
throw new RuntimeException(e);
}
float[] vertices = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
int[] indices = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
vao = gl.glGenVertexArrays();
vbo = gl.glGenBuffers();
ebo = gl.glGenBuffers();
gl.glBindVertexArray(vao);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo);
gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, ebo);
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices, GL.GL_STATIC_DRAW);
gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 0);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 3 * Float.BYTES);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(2, 2, GL.GL_FLOAT, false, 8 * Float.BYTES, 6 * Float.BYTES);
gl.glEnableVertexAttribArray(0);
texture = gl.glGenTextures();
gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8, lwjgl32.getWidth(), lwjgl32.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, lwjgl32.getImageData());
gl.glGenerateMipmap(GL.GL_TEXTURE_2D);
prog.use(gl);
gl.glUniform1i(gl.glGetUniformLocation(prog.getId(gl), "texture"), 0);
Util.checkError(gl, false);
}
@Override
protected void update(GL gl, long deltaFrame) {
gl.glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
prog.use(gl);
gl.glBindVertexArray(vao);
gl.glDrawElements(GL.GL_TRIANGLES, 6, GL.GL_UNSIGNED_INT, 0);
}
@Override
public void clean(GL gl) {
gl.glDeleteVertexArrays(vao);
gl.glDeleteBuffers(vbo);
gl.glDeleteBuffers(ebo);
ShaderProgram.clearUse(gl);
prog.dispose(gl);
}
顶点着色器
#version 330 core
layout (location = 0) in vec3 in_position;
layout (location = 1) in vec3 in_color;
layout (location = 2) in vec2 in_texCoord;
out vec3 color;
out vec2 texCoord;
void main() {
gl_Position = vec4(in_position, 1.0);
color = in_color;
texCoord = vec2(in_texCoord.x, in_texCoord.y);
}
片段着色器
#version 330 core
out vec4 frag_colour;
in vec3 color;
in vec2 texCoord;
uniform sampler2D texture;
void main() {
frag_colour = texture(texture, texCoord) * vec4(color, 1.0);
}
1我将 LWJGL3 的 GL## static 类 包装到单个接口和实现中,这样我就可以拥有一堆有状态的方法例如识别正在呈现的上下文等。我也尽力从界面中删除非核心功能,所以我什至不想使用已弃用的东西
仅看代码很难判断,但黑色四边形表示片段着色器中的这一行:
frag_colour = texture(texture, texCoord) * vec4(color, 1.0);
评估为 0。这意味着纹理不正确 read/bound,您的纹理坐标关闭或颜色为零向量。确保您的纹理图像已正确加载(文件存在,具有宽度和高度等)并且具有正确的格式。我通常调试着色器的做法是将每个参数设置为颜色,以在其具有正确的值时给出提示:
frag_colour = vec4(color, 1.0); //Makes sure the color is right
或
frag_colour = texture(texture, texCoord); //Makes sure the texture is loaded and bound
如果这还不能提供足够的信息,请提供更多详细信息:
frag_colour = vec4(color.x, color.x, color.x, 1.0);
或
frag_colour = vec4(texCoord.x, texCoord.x, texCoord.x, 1.0);
你只启用索引为0的顶点属性,但是这3次。
像这样调整您的代码:
gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 0);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 3 * Float.BYTES);
gl.glEnableVertexAttribArray(1); // <-------
gl.glVertexAttribPointer(2, 2, GL.GL_FLOAT, false, 8 * Float.BYTES, 6 * Float.BYTES);
gl.glEnableVertexAttribArray(2); // <------