Рендеринг Прозрачная прозрачность при рендеринге в текстуру при использовании прозрачности - PullRequest
1 голос
/ 02 апреля 2019

При рендеринге в текстуру (вторичный кадровый буфер) в OpenGL , все прозрачное перезаписывает прозрачность того, что ниже, а не добавляет прозрачность, как должна прозрачность. Это означает, что если я рендерим прозрачный объект поверх существующего непрозрачного объекта, результатом будет прозрачная текстура, даже если она должна быть непрозрачной.

https://i.stack.imgur.com/Y0YiT.png

На этом рисунке пространство отображается как фон, затем framebuffer изменяется, а затем отображается непрозрачный синий, а затем зеленый / красный. Текстура, на которую framebuffer рендерится, используется для рендеринга на исходную framebuffer (окно), и результат такой, какой вы видите.

Код:

Создание кадрового буфера / текстуры:

        int texture = glGenTextures();
        framebufferID = glGenFramebuffers();
        glBindFramebuffer(GL_FRAMEBUFFER,framebufferID);
        glBindTexture(GL_TEXTURE_2D, texture);
        int width,height;
        width = (int)(getMaster().getWindow().getWidth()*(xscale/(16f*getMaster().getGuiCamera().getWidth()))*1.2f);
        height = (int)(getMaster().getWindow().getHeight()*(yscale/9f)*1.15f);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,0);
        int depth = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, depth);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
        this.texture = new Texture(texture,width,height,true);
        glDrawBuffer(GL_FRONT_AND_BACK);

Здесь я пытался заставить работать буфер глубины, но он не оказал влияния на текстуру вывода.

Код рендеринга:

        getMaster().returnToViewportAfterFunction(new Vector2i(texture.getWidth(),texture.getHeight()),
            () -> getMaster().returnToFramebufferAfterFunction(framebufferID, () -> {

                shapeShader.bind();
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                model.bind();
                shapeShader.setUniform("color", 0f, 0f, 1f, 1f); //Blue
                shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale, yscale));
                glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);

                shapeShader.setUniform("color", 0f, 1f, 0f, 0.5f); //Green
                shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale/2f, yscale/2f));
                glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);

                shapeShader.setUniform("color", 1f, 0f, 0f, .2f); //Red
                shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale/4f, yscale/2f));
                glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);

                glDisable(GL_BLEND);

                model.unbind();
            })
        );
        //Renders the texture we just made
        shader.bind();
        model.bind();
        textureCoords.bind(texture);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        shader.setUniform("color", 1f, 1f, 1f, 1f);
        shader.setUniform("projection", camera.getProjectionForGuiWindow(getPosition(), xscale, yscale));
        glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);
        glDisable(GL_BLEND);

        model.unbind();

Рендеринг поверх непрозрачных объектов в framebuffer 0 с прозрачным объектом не приводит к тому, что результирующие пиксели становятся прозрачными, иначе они будут выглядеть как смесь glClearColor и непрозрачного объекта, так почему это происходит в framebuffer в котором я использую для рендеринга текстуры? Разве это не должно быть последовательным? Я чувствую, что, может быть, мне не хватает какой-то привязанности к моему framebuffer, но я не уверен, что именно. Я видел решение, в котором говорилось, что используется glColorMask(true,true,true,false), последнее ложное значение без альфа-записи, которое на первый взгляд кажется эффективным, но почему я должен отключать прозрачность, если прозрачность - то, к чему я стремлюсь? Это также, кажется, вызывает много проблем, если оставить его включенным. Кто-нибудь может дать некоторое понимание? Заранее спасибо!

РЕДАКТИРОВАТЬ: glColorMask не был решением после дальнейшего анализа.

Ответы [ 2 ]

1 голос
/ 02 апреля 2019

Вы должны использовать разделяемую функцию смешивания , которая обрабатывает значения RGB и Alpha отдельно: glBlendFuncSeparate . Для значений RGB вы продолжаете использовать GL_SRC_ALPHA, GL_SRC_ONE_MINUS_ALPHA. Для значений Alpha используйте что-то вроде GL_ONE, GL_ONE, чтобы все просто складывалось.

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
0 голосов
/ 03 апреля 2019

Для всех, кто интересуется, лучшим решением для моей проблемы было использование glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE) вместо glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINS) = GLBlendFunc

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...