C++ OpenGL纹理赢得';t画

C++ OpenGL纹理赢得';t画,c++,opengl,shader,sdl,soil,C++,Opengl,Shader,Sdl,Soil,我遵循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::in

我遵循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);

}
#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()
{
}
#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!
控制台日志:

#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。
怎么了?

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

解决方法是注释掉所有代码,除了清楚哪些代码有效(这是重要的第一步,您至少可以获得OpenGL输出)。然后添加代码,直到你们在屏幕上看到一些东西,任何东西


然后,通过重新编码代码,然后再返回到空白屏幕效果,再将其注释到你想要看到的东西。在你的SPRITE中,

是在<代码> //激活着色器< /代码>注释的情况下,假设要注释掉吗?@杰姆斯Bean,是“//绘制容器”下的行。然而,正如@JamesBean已经指出的那样,首先不要对它们进行注释,您正在尝试在没有激活任何程序的情况下进行绘制。其次,您的
shader
sprite
对象只是
initSystems
中的局部变量,获取它们的地址并将其存储以备以后使用对您没有帮助。您还没有设置投影矩阵。@derhass谢谢,现在它可以工作了:D