OpenGL sprite 以低质量绘制

Posted

技术标签:

【中文标题】OpenGL sprite 以低质量绘制【英文标题】:OpenGL sprite draws in low quality 【发布时间】:2016-05-21 10:11:27 【问题描述】:

我正在尝试使用 opengl glsl 和 glm 库来渲染精灵。 当我使用 glBegin 在遗留管道中渲染精灵时,glEnd 一切都很好,但是当我使用着色器时,旋转精灵后,它的绘制质量非常差,如图所示:

http://sm.uploads.im/t/I3lpf.png

我的渲染代码:

GLuint p;
GLuint vertex_shader, fragment_shader;
GLuint VBO, VAO;
glm::mat4 projection_matrix = glm::ortho(0.0F, 640.0F, 480.0F, 0.0F, -1.0F, 1.0F);

void sprite_init()

    p = glCreateProgram();

    // LOAD VERTEX SHADER //
    std::ifstream vf("E:\\vertex.sh");
    std::stringstream vs;
    vs << vf.rdbuf();

    std::ifstream ff("E:\\fraqment.sh");
    std::stringstream fs;
    fs << ff.rdbuf();

    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);

    char* buffer = new char[vs.str().size() + 1];
    memcpy(buffer, vs.str().c_str(), vs.str().size() + 1);
    glShaderSource(vertex_shader, 1, &buffer, NULL);
    free(buffer);

    buffer = new char[fs.str().size() + 1];
    memcpy(buffer, fs.str().c_str(), fs.str().size() + 1);
    glShaderSource(fragment_shader, 1, &buffer, NULL);
    free(buffer);

    glCompileShader(vertex_shader);
    glCompileShader(fragment_shader);

    glAttachShader(p, vertex_shader);
    glAttachShader(p, fragment_shader);
    glLinkProgram(p);

    GLfloat vertices[] =
    
        // POS //   // TEX //
        0.0F, 1.0F, 0.0F, 1.0F,
        1.0F, 0.0F, 1.0F, 0.0F,
        0.0F, 0.0F, 0.0F, 0.0F,

        0.0F, 1.0F, 0.0F, 1.0F,
        1.0F, 1.0F, 1.0F, 1.0F,
        1.0F, 0.0F, 1.0F, 0.0F
    ;

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

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindVertexArray(VAO);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);


void sprite_draw()

    glUseProgram(p);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glUniform1i(glGetUniformLocation(p, "image"), 0);

    // SET MATRIX //
    glm::vec2 size = glm::vec2(width, height);
    glm::vec2 position = glm::vec2(pos.x - 0.5F * size.x, pos.y - 0.5F * size.y);
    glm::vec3 col = glm::vec3(1.0F, 1.0F, 1.0F);

    glm::mat4 model_matrix;
    model_matrix = glm::translate(model_matrix, glm::vec3(position, 0.0f));

    model_matrix = glm::translate(model_matrix, glm::vec3(0.5F * size.x, 0.5F * size.y, 0.0f));
    model_matrix = glm::rotate(model_matrix, glm::radians(rotate), glm::vec3(0.0f, 0.0f, 1.0f));
    model_matrix = glm::translate(model_matrix, glm::vec3(-0.5F * size.x, -0.5F * size.y, 0.0f));

    model_matrix = glm::scale(model_matrix, glm::vec3(size, 1.0F));

    glUniformMatrix4fv(glGetUniformLocation(p, "projection"), 1, GL_FALSE, glm::value_ptr(projection_matrix));
    glUniformMatrix4fv(glGetUniformLocation(p, "model"), 1, GL_FALSE, glm::value_ptr(model_matrix));
    glUniform3f(glGetUniformLocation(p, "spriteColor"), col.x, col.y, col.z);

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    glBindVertexArray(0);

    glUseProgram(0);

顶点着色器:

#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>

out vec2 TexCoords;

uniform mat4 model;
uniform mat4 projection;

void main()

    TexCoords = vertex.zw;
    gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);

片段着色器:

#version 330 core
in vec2 TexCoords;
out vec4 color;

uniform sampler2D image;
uniform vec3 spriteColor;

void main()
    
    color = vec4(spriteColor, 1.0) * texture(image, TexCoords);
  

纹理设置:

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
this->textures.push_back(texture);

谢谢

【问题讨论】:

您是否设置了纹理过滤,例如LINEAR_MIPMAP_LINEAR 和(普遍存在的)各向异性过滤?否则,您可能会从多采样上下文中受益。 在 fs 中强制 alpha 为 1.0 是个坏主意,但可能不是您的主要问题 @brett-hale 是的,我使用 GL_NEAREST 纹理过滤 我猜你必须在你的情况下使用 MIPMAPed 过滤关键字。请显示你的纹理设置。 问题已解决。我刚刚将 GL_NEAREST 更改为 GL_LINEAR,现在它可以完美运行了。 【参考方案1】:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

您应该使用GL_LINEAR 过滤,而不是GL_NEAREST

【讨论】:

以上是关于OpenGL sprite 以低质量绘制的主要内容,如果未能解决你的问题,请参考以下文章

如何用OpenGL的点精灵(point sprite)绘制雪花?

如何用OpenGL的点精灵(point sprite)绘制雪花?

在现有 sdl_opengl 上下文上绘制小部件

Python OpenCV 以低质量读取视频

如何在OpenGL中将像素作为纹理绘制到多边形?

优化流媒体vbo openg