OpenGL纹理不会绘制

Posted

技术标签:

【中文标题】OpenGL纹理不会绘制【英文标题】:OpenGL Texture won't draw 【发布时间】:2016-12-17 15:06:22 【问题描述】:

我按照 opengl 教程创建了一个更加面向对象的版本。 我想绘制一个纹理,但唯一有效的是 glClearColor 命令。我不知道为什么它不起作用。我什么都试过了。代码如下:

Sprite.cpp

#include "Sprite.h"
#include <SOIL\SOIL.h>



Sprite::Sprite(const char* texturePath, float x, float y, GLuint width, GLuint height)

    Sprite::init(texturePath, x, y, width, height);



Sprite::~Sprite()



void Sprite::init(const char* texturePath, float x, float y, GLuint width, GLuint height)

    Logger::info("Initializing Sprite...");
    _x = x;
    _y = y;
    _width = width;
    _height = height;

    // Build and compile our shader program



    // Set up vertex data (and buffer(s)) and attribute pointers
    const GLfloat vertices[] = 
        // Positions                        // Colors           // Texture Coords
        _x,        _y,         0.0f,        0.0f, 0.0f, 0.0f,   1.0f, 1.0f,
        _x,        _y + _height, 0.0f,        0.0f, 0.0f, 0.0f,   1.0f, 0.0f,
        _x + _width, _y,         0.0f,        0.0f, 0.0f, 0.0f,   0.0f, 0.0f,
        _y + _width, _y + _height, 0.0f,        0.0f, 0.0f, 0.0f,   0.0f, 1.0f
    ;



    /*GLfloat 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 
    ;

    */





    constexpr GLuint indices[] =   // Note that we start from 0!
        0, 1, 3, // First Triangle
        1, 2, 3  // Second Triangle
    ;


    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    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);

    // Position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // Color attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);
    // TexCoord attribute
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0); // Unbind VAO


                          // Load and create a texture 
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture); // All upcoming GL_TEXTURE_2D operations now have effect on this texture object
                                           // Set the texture wrapping parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   // Set texture wrapping to GL_REPEAT (usually basic 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 twidth, theight;
    unsigned char* image = SOIL_load_image(texturePath, &twidth, &theight, 0, SOIL_LOAD_RGB);
    if (image == 0)
    
        Logger::fatalError("Image is null!");
    

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    glGenerateMipmap(GL_TEXTURE_2D);
    SOIL_free_image_data(image);
    glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.






    //_texture2 = texture2;
    Logger::info("Sprite initialization succesful!");



void Sprite::draw(Shader *shader)

/*  glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _texture1);
    glUniform1i(glGetUniformLocation(shader->_programID, "ourTexture1"), 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, _texture2);
    glUniform1i(glGetUniformLocation(shader->_programID, "ourTexture2"), 1);
    */









    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);


    // Bind Texture
    glBindTexture(GL_TEXTURE_2D, texture);

    if (texture == 0) 
        Logger::fatalError("texture1 is null");
    

    if (shader == 0) 
        Logger::fatalError("shader is null");
    


    if (VAO == 0) 
        Logger::fatalError("VAO is null");
    

    // Activate shader
//  glActiveTexture(GL_TEXTURE0);
//  glBindTexture(GL_TEXTURE_2D, texture);
    //glUniform1i(glGetUniformLocation(shader->_programID, "ourTexture"), 0);
    //shader->Use();

    // Draw container
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);


Shader.cpp

#include "Shader.h"



Shader::Shader(const GLchar* vertexShaderPath, const GLchar* fragmentShaderPath)

    std::string vertexCode;
    std::string fragmentCode;
    std::ifstream vertexShaderFile;
    std::ifstream fragmentShaderFile;
    // ensures ifstream objects can throw exceptions:
    vertexShaderFile.exceptions(std::ifstream::badbit);
    fragmentShaderFile.exceptions(std::ifstream::badbit);
    try
    
        // Open files
        vertexShaderFile.open(vertexShaderPath);
        fragmentShaderFile.open(fragmentShaderPath);
        std::stringstream vShaderStream, fShaderStream;
        // Read file's buffer contents into streams
        vShaderStream << vertexShaderFile.rdbuf();
        fShaderStream << fragmentShaderFile.rdbuf();
        // close file handlers
        vertexShaderFile.close();
        fragmentShaderFile.close();
        // Convert stream into GLchar array
        vertexCode = vShaderStream.str();
        fragmentCode = fShaderStream.str();
    
    catch (std::ifstream::failure e)
    
        Logger::info("ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ");
    
    const GLchar* vertexShaderCode = vertexCode.c_str();
    const GLchar* fragmentShaderCode = fragmentCode.c_str();

    Shader::compileShaders(vertexShaderCode, fragmentShaderCode);




void Shader::compileShaders(const GLchar* vertexShaderCode, const GLchar* fragmentShaderCode) 
    Logger::info("Compiling Shaders...");
    GLuint vertex, fragment;
    GLint success;
    GLchar infoLog[512];

    // Vertex Shader
    vertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex, 1, &vertexShaderCode, NULL);
    glCompileShader(vertex);
    // Print compile errors if any
    glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
    if (!success)
    
        glGetShaderInfoLog(vertex, 512, NULL, infoLog);
        Logger::fatalError("ERROR::SHADER::VERTEX::COMPILATION_FAILED");
    ;

    // Similiar for Fragment Shader
    fragment = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment, 1, &fragmentShaderCode, NULL);
    glCompileShader(fragment);
    // Print compile errors if any
    glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
    if (!success)
    
        glGetShaderInfoLog(fragment, 512, NULL, infoLog);
        Logger::fatalError("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED");
    ;



    // Shader Program
    this->_programID = glCreateProgram();
    glAttachShader(this->_programID, vertex);
    glAttachShader(this->_programID, fragment);
    glLinkProgram(this->_programID);
    // Print linking errors if any
    glGetProgramiv(this->_programID, GL_LINK_STATUS, &success);
    if (!success)
    
        glGetProgramInfoLog(this->_programID, 512, NULL, infoLog);
        Logger::fatalError("ERROR::SHADER::PROGRAM::LINKING_FAILED");
    

    // Delete the shaders as they're linked into our program now and no longer necessery
    glDeleteShader(vertex);
    glDeleteShader(fragment);
    Logger::info("Shader compilation succesful!");


void Shader::Use() 
    glUseProgram(this->_programID);



Shader::~Shader()


MainGame.cpp

#include "MainGame.h"





MainGame::MainGame()

    _window = nullptr;
    _screenWidth = 1024;
    _screenHeight = 768;
    _gameState = GameState::PLAY;



MainGame::~MainGame()




void MainGame::run() 
    initSystems();
    gameLoop();


void MainGame::initSystems() 
    //Initialize SDL
    SDL_Init(SDL_INIT_EVERYTHING);
    //Create Window
    _window = SDL_CreateWindow("Half Life 3", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _screenWidth, _screenHeight, SDL_WINDOW_OPENGL);
    //glViewport(0, 0, _screenWidth, _screenHeight);
    if (_window == nullptr) 
        Logger::fatalError("SDL Window could not be created!");
    
    SDL_GLContext glContext = SDL_GL_CreateContext(_window);
    if (glContext == nullptr) 
        Logger::fatalError("SDL_GL context could not be created");
    

    GLenum error = glewInit();
    if (error != GLEW_OK) 
        Logger::fatalError("Could not initialize glew!");
    

    Logger::info("Initialization succesful");

    //Double Buffer: Smooth, no flickering
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    glClearColor(0, 0, 1, 1.0);

    Shader shader("Shaders/Shader.vert", "Shaders/Shader.frag");
    _shader = &shader;
    Sprite sprite("Textures/wall.jpg", 0.5f, 0.5f, 100, 100);
    _texture = &sprite;



void MainGame::gameLoop() 
    while (_gameState != GameState::EXIT) 
        processInput();
        drawGame();
    

void MainGame::processInput() 
    SDL_Event evnt;
    while (SDL_PollEvent(&evnt) == true) 
        switch (evnt.type) 
        case SDL_QUIT:
            _gameState = GameState::EXIT;
        //  std::cout << "Quit Event" << std::endl;
            break;
        case SDL_MOUSEMOTION:
        //  std::cout << "x: " << evnt.motion.x << " y: " << evnt.motion.y << std::endl;
            break;
        
    

void MainGame::drawGame() 
//  glClearDepth(1.0);
//  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    //_shader->Use();

    // Bind Textures using texture units
    _texture->draw(_shader);



    // Swap the screen buffers
    SDL_GL_SwapWindow(_window);


片段着色器:

#version 330 core
in vec3 ourColor;
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture;

void main()

    color = texture(ourTexture, TexCoord);

顶点着色器:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main()

    gl_Position = vec4(position, 1.0f);
    ourColor = color;
    TexCoord = texCoord;

控制台日志:

Initialization succesful
Compiling Shaders...
Shader compilation succesful!
Initializing Sprite...
Sprite initialization succesful!

您看,一切都正确加载并正确初始化并且没有错误。它仍然只显示 glClearColor。 怎么了?

【问题讨论】:

在您的 sprite.cpp 中,//Activate shader 注释下的行是否应该被注释掉? @James Bean 是的,但是“// Draw container”下的行没有被注释掉 首先,正如@JamesBean 已经指出的那样,您正在尝试在没有激活任何程序的情况下进行绘制。其次,您的shadersprite 对象只是initSystems 中的局部变量,获取它们的地址并将其存储以备后用对您没有帮助。 你还没有设置投影矩阵。 @derhass 谢谢,现在可以了:D 【参考方案1】:

空白屏幕效果在 Open GL 图形中很常见。这意味着视图、相机、照明或其他东西的设置方式使您什么也看不见。

解决方法是注释掉你所有的代码,除了明确哪些有效(这是重要的第一步,你至少得到了 Open GL 输出)。然后添加代码,直到您在屏幕上看到一些东西,anything

然后,您可以将 anything ) 逐渐转移到您想看到的内容,方法是重新注释代码,如果返回到空白屏幕效果,请再次注释掉。

【讨论】:

以上是关于OpenGL纹理不会绘制的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenGL / LWJGL 绘制纹理四边形使用旧纹理

OpenCL - 绘制到 OpenGL 纹理崩溃

在 OpenGL 中绘制多个 2D 纹理

OpenGL 绘制纹理

我的OpenGL学习进阶之旅关于OpenGL ES 绘制纹理,因为加载纹理坐标设置错误,导致纹理无法渲染的问题

我的OpenGL学习进阶之旅关于OpenGL ES 绘制纹理,因为加载纹理坐标设置错误,导致纹理无法渲染的问题