纹理加载问题 OpenGL 无法弄清楚原因
Texture loading problem OpenGL cant figure out why
我在将纹理应用到图像时遇到问题。我只是找不到问题
代码在没有纹理代码的情况下工作正常。
主文件:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <filesystem>
#include <stb_image.h>
#include "Shaders/Shader.h"
bool isWireFrame = false;
const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 720;
void framebufferCallBack(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
isWireFrame = !isWireFrame;
}
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
{
std::cout << "GLFW did not init!" << std::endl;
return EXIT_FAILURE;
}
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Hello World", NULL, NULL);
if (window == NULL)
{
glfwTerminate();
return EXIT_FAILURE;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
return EXIT_FAILURE;
}
std::cerr << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;
/*
We have to tell OpenGL the size of the rendering window so OpenGL knows how we want to display the data and coordinates with respect to the window. We can set those dimensions via the glViewport function
*/
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glfwSetFramebufferSizeCallback(window, framebufferCallBack);
glfwSetKeyCallback(window, keyCallBack);
Shader shader("Shaders/glsl/vert.glsl", "Shaders/glsl/frag.glsl");
float vertices[] = {
// positions // tex coords
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
unsigned int VBO, VAO, EBO, texture;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
unsigned char* data = stbi_load("Images/Crate.png", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load the texture" << std::endl;
}
stbi_image_free(data);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
float timeValue = glfwGetTime();
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
Vector4 colour(0.0f, greenValue, 0.0f, 1.0f);
glBindTexture(GL_TEXTURE_2D, texture);
shader.use();
shader.setVec4("Colour", colour);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
if (isWireFrame == true)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
else if (isWireFrame == false)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shader.ID);
glfwTerminate();
return 0;
}
片段着色器:
#version 330 core
out vec4 fragColour;
uniform vec4 Colour;
in vec2 TexCoord;
uniform sampler2D Texture;
void main()
{
fragColour = texture(Texture, TexCoord);
}
顶点着色器:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos.xyz, 1.0);
TexCoord = aTexCoord;
}
没有错误。
这是我画的对象。
[]
这是我要绘制的实际图像:
[]
图像应该是一个矩形,但它是一个三角形我不知道为什么会这样,也许这些信息可以提供帮助。
编辑所以我发现我没有在
中使用正确的颜色格式
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
但格式参数之前是GL_RGB
而不是GL_RGBA
但现在我有一个半绘制的纹理:
stride 参数是错误的。您的属性由 5 个部分组成(x、y、z、u、v)。因此步幅是 5 * sizeof(float)
而不是 8 * sizeof(float)
.
另外纹理坐标的大小是2(u,v),不是3:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
由于图像格式为PNG,纹理格式为GL_RGBA
而不是GL_RGB
:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
我在将纹理应用到图像时遇到问题。我只是找不到问题
代码在没有纹理代码的情况下工作正常。
主文件:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <filesystem>
#include <stb_image.h>
#include "Shaders/Shader.h"
bool isWireFrame = false;
const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 720;
void framebufferCallBack(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
isWireFrame = !isWireFrame;
}
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
{
std::cout << "GLFW did not init!" << std::endl;
return EXIT_FAILURE;
}
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Hello World", NULL, NULL);
if (window == NULL)
{
glfwTerminate();
return EXIT_FAILURE;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
return EXIT_FAILURE;
}
std::cerr << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;
/*
We have to tell OpenGL the size of the rendering window so OpenGL knows how we want to display the data and coordinates with respect to the window. We can set those dimensions via the glViewport function
*/
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glfwSetFramebufferSizeCallback(window, framebufferCallBack);
glfwSetKeyCallback(window, keyCallBack);
Shader shader("Shaders/glsl/vert.glsl", "Shaders/glsl/frag.glsl");
float vertices[] = {
// positions // tex coords
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
unsigned int VBO, VAO, EBO, texture;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
unsigned char* data = stbi_load("Images/Crate.png", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load the texture" << std::endl;
}
stbi_image_free(data);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
float timeValue = glfwGetTime();
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
Vector4 colour(0.0f, greenValue, 0.0f, 1.0f);
glBindTexture(GL_TEXTURE_2D, texture);
shader.use();
shader.setVec4("Colour", colour);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
if (isWireFrame == true)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
else if (isWireFrame == false)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shader.ID);
glfwTerminate();
return 0;
}
片段着色器:
#version 330 core
out vec4 fragColour;
uniform vec4 Colour;
in vec2 TexCoord;
uniform sampler2D Texture;
void main()
{
fragColour = texture(Texture, TexCoord);
}
顶点着色器:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos.xyz, 1.0);
TexCoord = aTexCoord;
}
没有错误。
这是我画的对象。
[
这是我要绘制的实际图像:
[
图像应该是一个矩形,但它是一个三角形我不知道为什么会这样,也许这些信息可以提供帮助。
编辑所以我发现我没有在
中使用正确的颜色格式glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
但格式参数之前是GL_RGB
而不是GL_RGBA
但现在我有一个半绘制的纹理:
stride 参数是错误的。您的属性由 5 个部分组成(x、y、z、u、v)。因此步幅是 5 * sizeof(float)
而不是 8 * sizeof(float)
.
另外纹理坐标的大小是2(u,v),不是3:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
由于图像格式为PNG,纹理格式为GL_RGBA
而不是GL_RGB
:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);