OpenGL纹理无法正常工作-黑屏[关闭]

Posted

技术标签:

【中文标题】OpenGL纹理无法正常工作-黑屏[关闭]【英文标题】:OpenGL texture does not work with no errors - black screen [closed] 【发布时间】:2020-10-09 18:29:11 【问题描述】:

我只是不明白为什么它不起作用 - 它只是显示一个白色屏幕......(或黑色屏幕,因为glClearColor) PS。 > 纹理也破坏了其他一切...... 我检查了着色器和代码:没有错误,没有响应,什么都没有。包括质地。 我认为着色器是正确的,但我不知道其他任何事情。我也有所有的库:GLEW、GLFW、OPENGL,从 stb_image 复制的单个头文件...

代码如下:

#include <iostream>
#include <fstream>
#include <string>
#include "GL/glew.h"
#include "GLFW/glfw3.h"

#define ASSERT(x) if(!(x)) __debugbreak();
#define CALL(x) OpenGlClError(); x; ASSERT(OpenGlError(#x, __LINE__, __FILE__));

#define STB_IMAGE_IMPLEMENTATION
#include "extern/stb_image/stb_image_vendor/stb_image.h"

void OpenGlClError() 
    while (glGetError());

bool OpenGlError(const char* func, int line, const char* file) 
    while (GLenum error = glGetError()) 
        std::cout << "GLTest: OPENGL ERROR: " << error << " in function " << func << " at line " << line << ", FILE: " << file << "\n";
        return false;
    
    return true;


#define ASSERT(x) if(!(x)) __debugbreak();
#define CALL(x) OpenGlClError(); x; ASSERT(OpenGlError(#x, __LINE__, __FILE__));

class Texture 
private:
    unsigned int TextID;
    std::string FilePath;
    unsigned char* LocalBuffer;
    int Width, Height, BytesPixel;
public:
    Texture(const std::string path)
        : TextID(0), FilePath(path), LocalBuffer(nullptr), Width(0), Height(0), BytesPixel(0) 
        CALL(glGenTextures(1, &TextID));
        CALL(glBindTexture(GL_TEXTURE_2D, TextID));

        stbi_set_flip_vertically_on_load(1);
        LocalBuffer = stbi_load(path.c_str(), &Width, &Height, &BytesPixel, 4);

        CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
        CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
        CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
        CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));

        CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, LocalBuffer));
        CALL(glBindTexture(GL_TEXTURE_2D, 0));

        if (LocalBuffer)  //if localbuffer exists
            stbi_image_free(LocalBuffer);
        
    
    ~Texture() 
        glDeleteTextures(1, &TextID);
    
    void Bind(unsigned int slot = 0)
        CALL(glActiveTexture(GL_TEXTURE0 + slot));
        CALL(glBindTexture(GL_TEXTURE_2D, TextID));
    
    void Unbind() 
        glBindTexture(GL_TEXTURE_2D, 0);
    
;

static std::string ReadShader(const std::string& filename) 
    std::ifstream stream;
    std::string line;
    std::string str;
    stream.open(filename);
    while (getline(stream, line)) 
        str.append(line).append("\n");
    
    std::cout << str;
    stream.close();
    return str;

static unsigned int CompileShader(const std::string& source, unsigned int type) 
    unsigned int shader = glCreateShader(type);
    const char* src = source.c_str();
    glShaderSource(shader, 1, &src, nullptr);
    glCompileShader(shader);
    int result;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
    // i - int
    // v - vector
    if (result == GL_FALSE) 
        std::cout << "Shader cannot be compiled.\n" << (type == GL_VERTEX_SHADER ? "vertex s." : "fragments.") << "\n";
        int length;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
        char* message = (char*)_malloca(length * sizeof(char));
        glGetShaderInfoLog(shader, length, &length, message);
        std::cout << message << "\n";
        glDeleteShader(shader);
    
    return shader;

static int CreateShader(const std::string& vShader, const std::string& fShader) 
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(vShader, GL_VERTEX_SHADER);
    unsigned int fs = CompileShader(fShader, GL_FRAGMENT_SHADER);
    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program);
    glValidateProgram(program);
    glDeleteShader(vs);
    glDeleteShader(fs);
    return program;


int main() 
    glfwInit();
    //make window
    GLFWwindow* window;
    //std::cout << "GLTest:" << glGetString(GL_VERSION) << "\n";
    window = glfwCreateWindow(800, 500, "Modern OpenGL Test", NULL, NULL);
    glfwMakeContextCurrent(window);
    glewInit();

    float texver[16] = 
         -1.0f, -1.0f , 0.0f, 0.0f,
         1.0f, -1.0f, 1.0f, 0.0f,
         1.0f, 1.0f, 1.0f, 1.0f,
         -1.0f, -1.0f, 0.0f, 1.0f
    ;

    float texindex[6] = 
        0, 1, 2,
        2, 3, 0
    ;

    float vertices[12] = 
         1.0f, 1.0f,
         0.0f, -1.0f,
         1.0f, -1.0f,

         -1.0f, 1.0f,
          0.0f, 1.0f,
         -1.0f, -1.0f
    ;

    //unsigned int varray; //< dont actually need it...
    //glGenVertexArrays(1, &varray);
    //glBindVertexArray(varray);

    //unsigned int vb;
    //glGenBuffers(1, &vb);
    //glBindBuffer(GL_ARRAY_BUFFER, vb);
    //glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), vertices, GL_STATIC_DRAW);
    //
    //glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); //said hey we have this set up like that, links in vertex array
    //glEnableVertexAttribArray(0); //yea remember it

    unsigned int tb;
    glGenBuffers(1, &tb);
    glBindBuffer(GL_ARRAY_BUFFER, tb);
    glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), texver, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); //said hey we have this set up like that, links in vertex array
    glEnableVertexAttribArray(0); //yea remember it

    unsigned int shaders = CreateShader(ReadShader("shaders/basic_texture_vertex.shader"), ReadShader("shaders/basic_texture_fragment.shader"));
    glUseProgram(shaders);
    
    Texture tt("../!Assets/editor/img/intro_logo.png");
    tt.Bind();

    CALL(int location = glGetUniformLocation(shaders, "u_Texture"));
    CALL(glUniform1i(location, 0));

    CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));

    while (!glfwWindowShouldClose(window)) 
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(1, 1, 1, 1);
        //Drawing
        glDrawArrays(GL_TRIANGLES, 0, 6 * 2);


        glfwSwapBuffers(window);
        glfwPollEvents();

    
    glDeleteProgram(shaders);
    glfwTerminate();

【问题讨论】:

【参考方案1】:

您错过了为纹理坐标指定顶点属性。比如

unsigned int tb;
glGenBuffers(1, &tb);
glBindBuffer(GL_ARRAY_BUFFER, tb);
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), texver, GL_STATIC_DRAW);

// vertex cooridnates
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
glEnableVertexAttribArray(0);

// texture coordinates
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)(sizeof(float)*2));
glEnableVertexAttribArray(1);

glDrawArrays 的最后一个参数是顶点数。由于您只有 4 个顶点,因此参数不能是 6*2。 无论如何,既然你已经指定了一个数组索引,你似乎想要指定一个Index buffer。您必须使用glDrawElements 进行索引渲染。

索引必须是整数数据类型:

int texindex[6] = 
    0, 1, 2,
    0, 2, 3
;

生成索引(GL_ELEMENT_ARRAY_BUFFER)缓冲区:

unsigned int ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(int), texindex, GL_STATIC_DRAW); 

画出三角形:

glDrawArrays(GL_TRIANGLES, 0, 6 * 2);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

【讨论】:

@MegapolisPlayer 此外,texver 中有一个错误。最后一个顶点是两次。将-1.0f, -1.0f 更改为-1.0f, 1.0f

以上是关于OpenGL纹理无法正常工作-黑屏[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL代码适用于GLFW,但不适用于Qt OpenGL

OpenGL 纹理无法正常工作

无法使用 OpenGL 显示纹理

OpenGL - 在 NVIDIA 卡上渲染到纹理时出现 FBO 黑屏

为什么我的2D OpenGL纹理无法正确加载? [关闭]

OpenGL ES 无法正常工作