纹理不适用于我在 C++ 和 OpenGL 中的立方体
Posted
技术标签:
【中文标题】纹理不适用于我在 C++ 和 OpenGL 中的立方体【英文标题】:Texture doesn't apply to my cube in C++ & OpenGL 【发布时间】:2019-08-05 21:50:23 【问题描述】:我正在关注 C++ 中的 OpenGL tutorial。 我的问题是关于纹理我的立方体。该程序似乎可以正确加载纹理,但没有显示预期的结果,我的立方体看起来是灰色的。
我通常应该拥有的东西: 我有什么:我已经尝试更改我的着色器(例如混合值),但它并没有改变任何东西。
这是我的代码:
head.h#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <chrono>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.hpp"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
shader.hpp
#include "head.h"
/*TODO -- refresh shader every sec*/
class Shader
public:
Shader(std::string const& nameFragment, std::string const& nameVertex)
: nameFragment_(nameFragment), nameVertex_(nameVertex)
update();
void update()
if (nameFragment_.empty() || nameVertex_.empty() || (nameFragment_.empty() && nameVertex_.empty()))
return;
bool recreate = false;
std::ifstream stream(nameFragment_);
std::string tmp = std::string(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>());
stream.close();
if (tmp != fragment_)
setFragment(tmp);
recreate = true;
stream.open(nameVertex_);
tmp = std::string(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>());
stream.close();
if (tmp != vertex_)
setVertex(tmp);
recreate = true;
if (recreate)
createFragmentObject();
createVertexObject();
createProgramObject();
deleteUselessShaders();
std::cout << nameFragment_ << " & " << nameVertex_ << " Shaders loaded.\n";
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
void use()
glUseProgram(programObject_);
void setFragmentName(std::string const& name)
nameFragment_ = name;
void setVertexName(std::string const& name)
nameVertex_ = name;
std::string getFragmentName()
return nameFragment_;
std::string getVertexName()
return nameVertex_;
void setFragment(std::string const& fragment)
fragment_ = fragment;
fs_ptr_ = fragment_.c_str();
const GLchar*& getFragment()
return fs_ptr_;
void setVertex(std::string const& vertex)
vertex_ = vertex;
vs_ptr_ = vertex_.c_str();
const GLchar*& getVertex()
return vs_ptr_;
void createVertexObject()
/*Creating a VS object*/
vertexObject_ = glCreateShader(GL_VERTEX_SHADER);
/*Link the VS code to the VS object*/
glShaderSource(vertexObject_, 1, &vs_ptr_, NULL);
glCompileShader(vertexObject_);
/*Testing the VS compilation*/
int success;
char infoLog[512];
glGetShaderiv(vertexObject_, GL_COMPILE_STATUS, &success);
if (!success)
glGetShaderInfoLog(vertexObject_, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
const unsigned int & getVertexObject()
return vertexObject_;
void createFragmentObject()
/*As the VS, same for FS*/
fragmentObject_ = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentObject_, 1, &fs_ptr_, NULL);
glCompileShader(fragmentObject_);
int success;
char infoLog[512];
glGetShaderiv(fragmentObject_, GL_COMPILE_STATUS, &success);
if (!success)
glGetShaderInfoLog(fragmentObject_, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
const unsigned int& getFragmentObject()
return fragmentObject_;
void createProgramObject()
/*Creating the program Shader*/
programObject_ = glCreateProgram();
glAttachShader(programObject_, vertexObject_);
glAttachShader(programObject_, fragmentObject_);
glLinkProgram(programObject_);
int success;
char infoLog[512];
/*Testing PS compilation*/
glGetProgramiv(programObject_, GL_LINK_STATUS, &success);
if (!success)
glGetProgramInfoLog(programObject_, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::COMPILATION_FAILED\n" << infoLog << std::endl;
const unsigned int& getProgramObject()
return programObject_;
void deleteUselessShaders()
/*Deleting shaders already used*/
glDeleteShader(vertexObject_);
glDeleteShader(fragmentObject_);
void setBool(const std::string& name, bool value) const
glUniform1i(glGetUniformLocation(programObject_, name.c_str()), (int)value);
// ------------------------------------------------------------------------
void setInt(const std::string& name, int value) const
glUniform1i(glGetUniformLocation(programObject_, name.c_str()), value);
// ------------------------------------------------------------------------
void setFloat(const std::string& name, float value) const
glUniform1f(glGetUniformLocation(programObject_, name.c_str()), value);
// ------------------------------------------------------------------------
void setVec2(const std::string& name, const glm::vec2& value) const
glUniform2fv(glGetUniformLocation(programObject_, name.c_str()), 1, &value[0]);
void setVec2(const std::string& name, float x, float y) const
glUniform2f(glGetUniformLocation(programObject_, name.c_str()), x, y);
// ------------------------------------------------------------------------
void setVec3(const std::string& name, const glm::vec3& value) const
glUniform3fv(glGetUniformLocation(programObject_, name.c_str()), 1, &value[0]);
void setVec3(const std::string& name, float x, float y, float z) const
glUniform3f(glGetUniformLocation(programObject_, name.c_str()), x, y, z);
// ------------------------------------------------------------------------
void setVec4(const std::string& name, const glm::vec4& value) const
glUniform4fv(glGetUniformLocation(programObject_, name.c_str()), 1, &value[0]);
void setVec4(const std::string& name, float x, float y, float z, float w) const
glUniform4f(glGetUniformLocation(programObject_, name.c_str()), x, y, z, w);
// ------------------------------------------------------------------------
void setMat2(const std::string& name, const glm::mat2& mat) const
glUniformMatrix2fv(glGetUniformLocation(programObject_, name.c_str()), 1, GL_FALSE, &mat[0][0]);
// ------------------------------------------------------------------------
void setMat3(const std::string& name, const glm::mat3& mat) const
glUniformMatrix3fv(glGetUniformLocation(programObject_, name.c_str()), 1, GL_FALSE, &mat[0][0]);
// ------------------------------------------------------------------------
void setMat4(const std::string& name, const glm::mat4& mat) const
glUniformMatrix4fv(glGetUniformLocation(programObject_, name.c_str()), 1, GL_FALSE, &mat[0][0]);
private:
std::string nameFragment_;
std::string nameVertex_;
std::string vertex_;
std::string fragment_;
const GLchar *vs_ptr_;
const GLchar *fs_ptr_;
unsigned int vertexObject_;
unsigned int fragmentObject_;
unsigned int programObject_;
;
main.cpp
/*mises à l’échelle, puis les rotations et enfin les translations*/
/*glm::mat4; mat = glm::mat4(1.0f);*/
#include "head.h"
#define FPS 62
#define WIDTH 800
#define HEIGHT 600
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
int main()
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //For MacOS
#endif
/*Window initialization*/
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Hello Window!", NULL, NULL);
if (window == NULL)
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*GLAD initialization*/
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
// configure global opengl state
// -----------------------------
glEnable(GL_DEPTH_TEST);
/*Initialize shaders*/
Shader myShaders("./Shaders/Hello.fs", "./Shaders/Hello.vs");
/*Vertices*/
float vertices[] =
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
;
glm::vec3 cubePositions[] =
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3(2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3(1.3f, -2.0f, -2.5f),
glm::vec3(1.5f, 2.0f, -2.5f),
glm::vec3(1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
;
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// load and create a texture
// -------------------------
unsigned int texture1, texture2;
// texture 1
// ---------
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
// The FileSystem::getPath(...) is part of the GitHub repository so we can find files on any IDE/platform; replace it with your own image path.
unsigned char* data = stbi_load(("./Textures/container.jpg"), &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 texture" << std::endl;
stbi_image_free(data);
// texture 2
// ---------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
data = stbi_load("./Textures/awesomeface.png", &width, &height, &nrChannels, 0);
if (data)
// note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
else
std::cout << "Failed to load texture" << std::endl;
stbi_image_free(data);
myShaders.use();
myShaders.setInt("texture1", 0);
myShaders.setInt("texture2", 1);
/*To get a wireframe style*/
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
/*Render Loop*/
double lasttime = glfwGetTime();
while (!glfwWindowShouldClose(window))
glfwSwapBuffers(window);
while (glfwGetTime() < lasttime + 1.0 / FPS)
processInput(window);
glClearColor(0.2f, 0.7f, 0.6f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now!
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
/*Activating our shader*/
myShaders.use();
// create transformations
glm::mat4 view = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
glm::mat4 projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), (float)WIDTH / (float)HEIGHT, 0.1f, 100.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
// pass transformation matrices to the shader
myShaders.setMat4("projection", projection); // note: currently we set the projection matrix each frame, but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once.
myShaders.setMat4("view", view);
// render boxes
glBindVertexArray(VAO);
for (unsigned int i = 0; i < 10; i++)
// calculate the model matrix for each object and pass it to shader before drawing
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, cubePositions[i]);
float angle = 20.0f * i;
model = glm::rotate(model, glm::radians((float)angle), glm::vec3(1.0f, 0.3f, 0.5f));
myShaders.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glfwPollEvents();
lasttime += 1.0 / FPS;
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
/*Resize*/
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
glViewport(0, 0, width, height);
/*Handle inputs*/
void processInput(GLFWwindow* window)
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
Hello.fs
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
FragColor = mix(texture(texture1,TexCoord),texture(texture2,TexCoord),0.2f);
Hello.vs
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor; // la variable aColor a l'attribut de position 1
layout (location = 2) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);
【问题讨论】:
【参考方案1】:看看:
// texture coord attribute glVertexAttribPointer(1, [...] );
对比你的着色器:
layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; // la variable aColor a l'attribut de position 1 layout (location = 2) in vec2 aTexCoord;
所以,你实际上告诉 GL 使用你的纹理坐标作为aColor
属性。而且由于您根本没有为属性位置 2 (aTexCoord
) 启用数组,因此所有顶点将看到相同的纹理坐标值,因此纹理采样将在所有地方从纹理返回相同的颜色...
【讨论】:
以上是关于纹理不适用于我在 C++ 和 OpenGL 中的立方体的主要内容,如果未能解决你的问题,请参考以下文章
Opengl Array Texture,适用于原始数据,但不适用于图像数据