纹理不适用于我在 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 纹理不适用于大于 1x1 的分辨率

OpenGL/Glew C++ 纹理不适用

Opengl Array Texture,适用于原始数据,但不适用于图像数据

如何纹理 Opengl glut 对象(C++)

将 GLubyte* 转换为 GLuint* 用于 alpha 纹理 Opengl 3.0 / c++ / Win32

OpenGL 旋转 2D 纹理