尝试使用https://learnopengl.com/Getting-started/Textures课程学习OpenGL 3时,在未应用纹理(或未以我期望的方式应用纹理)时遇到了一个问题。
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import java.nio.ByteBuffer;
import java.util.Random;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL33.*;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Learn33 {
static long window;
static float triangles[] = {
// 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
};
static int triangleVertexArray;
static int indices[] = {
0, 1, 3,
1, 2, 3
};
static Shader shader;
static int texture;
public static void main(String[] args) {
try {
init();
shader = Shader.load("texture"); // shader loading, compiling, linking
loadModel();
loop();
} finally {
glfwTerminate();
}
}
private static void loadModel() {
triangleVertexArray = glGenVertexArrays();
int triangleDataBuffer = glGenBuffers();
int triangleIndexBuffer = glGenBuffers();
glBindVertexArray(triangleVertexArray);
glBindBuffer(GL_ARRAY_BUFFER, triangleDataBuffer);
glBufferData(GL_ARRAY_BUFFER, triangles, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 32, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, triangleDataBuffer);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 32, 12);
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, false, 32, 24);
glEnableVertexAttribArray(2);
//texture
texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width = 512;
int height = 512;
byte[] pixels = new byte[width * height * 3];
new Random().nextBytes(pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, ByteBuffer.wrap(pixels));
glGenerateMipmap(GL_TEXTURE_2D);
shader.use(); // same as glUseProgram(id);
shader.setInt("texture1", 0); // same as glUniform1i(glGetUniformLocation(id, "texture1"), 0)
}
private static void loop() {
GL.createCapabilities();
while (!glfwWindowShouldClose(window)) {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
shader.use();
glBindVertexArray(triangleVertexArray);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
}
private static void init() {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
}
glfwMakeContextCurrent(window);
GL.createCapabilities();
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(window, (wnd, width, height) -> glViewport(0, 0, width, height));
}
}
顶点着色器:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 vertexColor;
out vec2 textureCoordinates;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
vertexColor = aColor;
textureCoordinates = aTexCoord;
}
片段着色器:
#version 330 core
in vec3 vertexColor;
in vec2 textureCoordinates;
out vec4 FragColor;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, textureCoordinates);
}
由于我用随机值填充纹理数据,所以我希望有嘈杂的图案。实际上,结果是黑色矩形:
当我将片段着色器更改为:
FragColor = vec4(textureCoordinates, 0.0, 1.0);
因此问题一定在于如何填充纹理像素或将其传递给Open GL。可能是什么?会感谢您提供任何帮助,包括调试建议。
更新。有用的代码来检查错误。如果将其放入纹理加载代码或渲染循环中,则什么也不打印。
private static void checkErrors() {
int i = glGetError();
if (i != GL_NO_ERROR) {
System.err.println("Error code: " + i);
}
}
解决方案 如评论中所建议,此处Empty texture when using glTexImage2D with ByteBuffer in LWJGL
报告了类似的问题更改为
后 byte[] pixels = new byte[width * height * 3];
new Random().nextBytes(pixels);
ByteBuffer buffer = BufferUtils.createByteBuffer(pixels.length);
buffer.put(pixels);
buffer.flip();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);