OpenGL 2d 纹理 class 不工作但相同的代码在主循环中的 class 之外工作?

OpenGL 2d texture class isn't working but same code works outside class in main loop?

我正在学习 OpenGL https://learnopengl.com/ 我想获取 2D 纹理代码并将其放入 class。该代码在主文件中运行良好,但复制并粘贴到纹理 class 中的相同代码根本不起作用。导致黑色。我试过使用错误检查,但什么也没有出现。我想知道为什么它不起作用。

Main.cpp 文件:

#include <iostream>
#include <chrono>
#include <thread>

#include "GL/glew.h"
#include "GLFW/glfw3.h"

#define STB_IMAGE_IMPLEMENTATION
#include "STB/stb_image.h"

#include "Shader.h"
#include "Texture2D.h"
using namespace std::chrono_literals;

//Keeps viewport same size of window when the window is resized
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window) {
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    else
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

int main() {
    stbi_set_flip_vertically_on_load(true);

    //Vertices and Indices
    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 
    };
    unsigned int indices[] = {  // note that we start from 0!
        0, 2, 3,   // first triangle
        0, 1, 2    // second triangle
    };

    //GLFW Initialization
    if (!glfwInit()) { std::cerr << "Shit, GLFW Didn't INIT Properly" << std::endl; std::this_thread::sleep_for(3s); return -1; }
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    //GLFW Window Creation
    GLFWwindow* w = glfwCreateWindow(800,600,"WET ASS PUSSY",NULL,NULL);
    if (!w) { glfwTerminate(); std::cerr << "Failed to Make Window" << std::endl; std::this_thread::sleep_for(3s); return -1; }
    glfwMakeContextCurrent(w);

    //GLEW Initialization
    if (glewInit() != GLEW_OK) { glfwTerminate(); std::cerr << "Shit, GLEW Didn't Init Properly" << std::endl; std::this_thread::sleep_for(3s); return -1; }
    std::cout << glGetString(GL_VERSION) << std::endl;

    //Viewport and Window Resizing Callback Setup
    glViewport(0, 0, 800, 600);
    glfwSetFramebufferSizeCallback(w, framebuffer_size_callback); //Fn set as callback when resizing window

    /*
    //Create Texture
    unsigned int texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    // set the texture wrapping/filtering options (on the currently bound texture object)
    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);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //Load Texture Data
    int width, height, nrChannels;
    unsigned char* data = stbi_load("Textures/stoneBrickWall.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);
    */
    Texture2D tex("Textures/stoneBrickWall.jpg", GL_RGB, GL_RGB, GL_REPEAT, GL_LINEAR);

    //Vector Buffer/Element Buffer/Vector Array Handling
    unsigned int vBuff;
    glGenBuffers(1, &vBuff);

    unsigned int EBO;
    glGenBuffers(1, &EBO);

    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, vBuff);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    //glBindTexture(GL_TEXTURE_2D, texture);
    tex.use();

    //Vertex Handling Instructions
    //Position
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    //Color
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3*sizeof(float)));
    glEnableVertexAttribArray(1);
    //Texture
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0);

    //Make Shader
    Shader shader("Shader.vs", "Shader.fs");

    shader.use();

    //Render Loop
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    while (!glfwWindowShouldClose(w)) {
        processInput(w);

        glClear(GL_COLOR_BUFFER_BIT);
        //render here--
        shader.use();
        glBindVertexArray(VAO);
        tex.use();

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glUseProgram(0);
        glBindVertexArray(0);
        //--

        glfwSwapBuffers(w);
        glfwPollEvents();
    }

    //Cleanup
    glfwDestroyWindow(w);
    glfwTerminate();

    return 0;
}

Texture2D.h:

#pragma once

#include "GL/glew.h"

#include <iostream>

class Texture2D {
public:
    unsigned int ID = 0;
    int width = 0, height = 0, nrChannels = 0;

    Texture2D(const char* imgPath, GLint internalFormat, GLenum format, GLint sWrapMode, GLint tWrapMode, GLint minFilterMode, GLint magFilterMode);
    Texture2D(const char* imgPath, GLint internalFormat, GLenum format, GLint wrapMode, GLint filterMode) { Texture2D(imgPath, internalFormat, format, wrapMode, wrapMode, filterMode, filterMode); }

    void use();
    void use(unsigned int textureUnitNum);

    GLuint checkError(const char* context);
};

Texture2D.cpp:

#include "Texture2D.h"

#include "STB/stb_image.h"

Texture2D::Texture2D(const char* imgPath, GLint internalFormat, GLenum format, GLint sWrapMode, GLint tWrapMode, GLint minFilterMode, GLint magFilterMode) {
    //Create Texture
    glGenTextures(1, &ID);
    glBindTexture(GL_TEXTURE_2D, ID);

    // set the texture wrapping/filtering options (on the currently bound texture object)
    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);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //Load Texture Data
    unsigned char* data = stbi_load("Textures/stoneBrickWall.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);

    checkError("Texture Creation");
}

void Texture2D::use() {
    glBindTexture(GL_TEXTURE_2D, ID);
    checkError("Binding Texture");
}

void Texture2D::use(unsigned int textureUnitNum) {
    glActiveTexture(GL_TEXTURE0 + textureUnitNum);
    use();
}

GLuint Texture2D::checkError(const char* context)
{
    GLuint err = glGetError();
    if (err > 0) {
        std::cout << "0x" << std::hex << err << " glGetError() in " << context
            << std::endl;
    }
    return err;
}

这个构造函数是问题所在:

Texture2D(const char* imgPath, GLint internalFormat, GLenum format, GLint wrapMode, GLint filterMode) {
    Texture2D(imgPath, internalFormat, format, wrapMode, wrapMode, filterMode, filterMode);
}

这会创建一个 Texture2D 类型的匿名局部变量,然后将其丢弃,使 Texture2D 对象本身(其构造函数现在 运行)完全未初始化。

我认为您打算改用 delegating constructor。区别很小但很重要:

Texture2D(const char* imgPath, GLint internalFormat, GLenum format, GLint wrapMode, GLint filterMode) 
    : Texture2D(imgPath, internalFormat, format, wrapMode, wrapMode, filterMode, filterMode) {}