6
votes

I am trying to render a sprite using opengl glsl and glm library. when i render sprite in legacy pipeline using glBegin, glEnd everything is fine but when i use shaders, after rotating sprite its draws in really poor quality as you can see in the picture:

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

My rendering code:

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);
}

Vertex Shader:

#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);
}

Fragment Shader:

#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);
}  

Texture setup:

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);

Thanks

1
Are you setting up texture filtering, e.g., LINEAR_MIPMAP_LINEAR, and (ubiquitous) anisotropic filtering? Otherwise, you might benefit from a multi-sampling context.Brett Hale
Forcing alpha to 1.0 in fs is bad idea, but probably not your main problemAndreas
@brett-hale Yes, i use GL_NEAREST texture filteringAsh
I guess you must use MIPMAPed filtering keywords in your case.Please show your texture setup.Michael IV
problem solved. I've just changed GL_NEAREST to GL_LINEAR and now it is perfectly works.Ash

1 Answers

2
votes
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

You should use GL_LINEAR filtering, not GL_NEAREST.