[英]OpenGL ES 2.0 When sampling texture on a fullscreen quad weird edge is being rendered
我正在努力在已经渲染的帧之上渲染一个简单的叠加图像。 框架由 mapbox 库渲染,我在 mapbox 渲染框架后调用我的渲染代码对其进行了修改。 我不知道我在 mapbox 库已经渲染的帧之上渲染这一事实是否重要,但也许是,所以我在这里提到它。
这个问题似乎与纹理有关。 我尝试渲染的图像是一个带有红色和透明方块的棋盘。 图像 bitmap 没有任何边缘。 图像是可见的,但边缘也是红色的,这不是我想要的,我已经花了几天时间试图找出这些边缘被渲染的原因。 如果有人能告诉我我做错了什么,我将不胜感激。
namespace mbgl {
void MapOverlayRenderer::arm() { // called when rendering surface has changed
releaseLog("MOR a");
program = createProgram();
vertexBuffer = createVertexBuffer();
indexBuffer = createIndexBuffer();
glGenTextures(1, &texture);
fillTexture();
}
void MapOverlayRenderer::render() { // called just after mapbox frame has rendered
if (!_image.valid()) {
return;
}
glUseProgram(program);
auto positionHandle = glGetAttribLocation(program, "vertexData");
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glEnableVertexAttribArray(positionHandle);
GLint numberOfValuesPerVertex = 4;
GLsizei stride = numberOfValuesPerVertex * sizeof(GLfloat);
glVertexAttribPointer(positionHandle, numberOfValuesPerVertex, GL_FLOAT, false, stride, nullptr);
auto imagePositionHandle = glGetUniformLocation(program, "imagePosition");
GLfloat imagePosition[] = {_leftPadding, _topPadding, _rightPadding, _bottomPadding};
glUniform4fv(imagePositionHandle, 1, imagePosition);
auto imageTextureHandle = glGetUniformLocation(program, "imageTexture");
glUniform1i(imageTextureHandle, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
auto numberOfVertices = 6;
glDrawElements(GL_TRIANGLES, numberOfVertices, GL_UNSIGNED_INT, nullptr);
glDisableVertexAttribArray(positionHandle);
}
void MapOverlayRenderer::setImage(float leftPadding, float topPadding, float rightPadding,
float bottomPadding, PremultipliedImage &&image) { // is called when I pass new image to be rendered
this->_image = std::move(image);
this->_leftPadding = leftPadding;
this->_topPadding = topPadding;
this->_rightPadding = rightPadding;
this->_bottomPadding = bottomPadding;
fillTexture();
}
void MapOverlayRenderer::removeImage() {
this->_leftPadding = 0.0f;
this->_topPadding = 0.0f;
this->_rightPadding = 0.0f;
this->_bottomPadding = 0.0f;
this->_image = PremultipliedImage();
}
GLuint MapOverlayRenderer::createVertexBuffer() {
GLuint result;
glGenBuffers(1, &result);
std::array<GLfloat, 16u> vertices{
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
glBindBuffer(GL_ARRAY_BUFFER, result);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
return result;
}
GLuint MapOverlayRenderer::createIndexBuffer() {
GLuint result;
glGenBuffers(1, &result);
std::array<GLuint, 6u> indices{
0u, 1u, 2u,
2u, 1u, 3u
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices, GL_STATIC_DRAW);
return result;
}
GLuint MapOverlayRenderer::createVertexShader() {
auto vertexShaderCode = R"(
precision highp float;
precision highp int;
precision highp sampler2D;
attribute vec4 vertexData;
varying vec2 fullscreenTextureCoordinates;
void main() {
fullscreenTextureCoordinates = vertexData.zw;
gl_Position = vec4(vertexData.xy, 0.0, 1.0);
})";
auto shader = loadShader(GL_VERTEX_SHADER, &vertexShaderCode);
return shader;
}
GLuint MapOverlayRenderer::createFragmentShader() {
auto fragmentShaderCode = R"(
precision highp float;
precision highp int;
precision highp sampler2D;
varying vec2 fullscreenTextureCoordinates;
uniform vec4 imagePosition;
uniform sampler2D imageTexture;
void main() {
float left = imagePosition[0];
float top = imagePosition[1];
float right = imagePosition[2];
float bottom = imagePosition[3];
if (fullscreenTextureCoordinates[0] < left ||
fullscreenTextureCoordinates[0] > right ||
fullscreenTextureCoordinates[1] > 1.0 - top ||
fullscreenTextureCoordinates[1] < 1.0 - bottom) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
} else {
float imageHorizontalCoordinate = (fullscreenTextureCoordinates[0] - left) / (right - left);
float imageVerticalCoordinate = 1.0 - (fullscreenTextureCoordinates[1] - top) / (bottom - top);
vec2 imageTextureCoordinates = vec2(imageHorizontalCoordinate, imageVerticalCoordinate);
gl_FragColor = texture2D(imageTexture, imageTextureCoordinates);
}
})";
auto shader = loadShader(GL_FRAGMENT_SHADER, &fragmentShaderCode);
return shader;
}
GLuint MapOverlayRenderer::createProgram() {
auto vertexShader = createVertexShader();
auto fragmentShader = createFragmentShader();
auto result = glCreateProgram();
glAttachShader(result, vertexShader);
glAttachShader(result, fragmentShader);
glLinkProgram(result);
return result;
}
GLuint MapOverlayRenderer::loadShader(GLenum type, GLchar const *const *shaderCode) {
auto shader = glCreateShader(type);
glShaderSource(shader, 1, shaderCode, nullptr);
glCompileShader(shader);
return shader;
}
void MapOverlayRenderer::fillTexture() {
if (!_image.valid()) {
return;
}
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(_image.size.width), static_cast<GLsizei>(_image.size.height), 0, GL_RGBA,
GL_UNSIGNED_BYTE, _image.data.get());
glGenerateMipmap(GL_TEXTURE_2D);
}
}
默认纹理环绕模式设置为环绕到纹理的另一侧。 如果进行任何过滤,这将最终从纹理的另一侧采样像素,这解释了细红色边框。
要将其更改为夹紧,请在绑定纹理后在fillTexture
中使用它:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.