繁体   English   中英

OpenGL ES 2.0 在渲染全屏四边形奇怪边缘上的采样纹理时

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM