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)绘制雪花?