Соединить две (или более) текстуры в одну

111
26 октября 2021, 05:10

Долгое время воевал один с этой задачей, но больше сил нет. Простая задача - объединить две (или более) картинки в одну, чтобы наложить на эту общую шейдер.

Вообще всё началось с того, что свет накладывается отдельной картинкой, но шейдеры почему-то не учитывают положение на экране и применяют эффект к центру.

На чём остановился сейчас:

Функция для создания фреймбуффера

void glGenTextureFromFramebuffer(GLuint *t, GLuint *f, GLsizei w, GLsizei h)
{
    glGenFramebuffers(1, f);
    glGenTextures(1, t);
    glBindFramebuffer(GL_FRAMEBUFFER, *f);
    glBindTexture(GL_TEXTURE_2D, *t);
    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);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *t, 0);
    GLuint depthbuffer;
    glGenRenderbuffers(1, &depthbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE)
        warning("Framebuffer status", "wtf");// status);
}

Отрисовка с помощью

void test_draw2(GLuint* texture, int x, int y, int w, int h) {
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBindTexture(GL_TEXTURE_2D, *texture);
    glBegin(GL_QUADS); {
        glTexCoord2d(0, 0); glVertex3f(x, y, 0);
        glTexCoord2d(1, 0); glVertex3f(x + w, y, 0);
        glTexCoord2d(1, 1); glVertex3f(x + w, y + h, 0);
        glTexCoord2d(0, 1); glVertex3f(x, y + h, 0);
    } glEnd();
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
}

Использование:

// obj1 и obj2 без буффера рендерятся как надо.
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
test_draw2(&obj1, 1920 / 2.f, 1080 / 2.f, width, height);
test_draw2(&obj2, 1920 / 2.f, 1080 / 2.f, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
test_draw2(&_texture, 1920 / 2.f, 1080 / 2.f, width, height);

Результат: чёрный квадрат.

Изменено: добавил код шейдера, хоть и не очень понимаю, как он поможет сложить текстуры в одну. Его суть - наложить эффект color dodge, чтобы симулировать свет в 2д игре со слоями. С радостью бы использовал обычный SDL2, но тот не поддерживает шейдеры.

#version 120
uniform sampler2D texture;
uniform sampler2D background;
float blendColorDodge(float base, float blend) {
    return (blend==1.0)?blend:min(base/(1.0-blend),1.0);
}
vec3 blendColorDodge(vec3 base, vec3 blend) {
    return vec3(blendColorDodge(base.r,blend.r),blendColorDodge(base.g,blend.g),blendColorDodge(base.b,blend.b));
}
vec3 blendColorDodge(vec3 base, vec3 blend, float opacity) {
    return (blendColorDodge(base, blend) * opacity + base * (1.0 - opacity));
}
void main (void)
{
    vec4 c = texture2D(texture, gl_TexCoord[0].st);
    vec4 blend = texture2D(background, gl_TexCoord[0].st);
    vec3 f = blendColorDodge(c.rgb, blend.rgb);
    gl_FragColor = vec4(f.r, f.g, f.b, c.a );
}
READ ALSO
Несколько функций main

Несколько функций main

Легален ли следующий код с точки зрения стандарта?

99
C++ - volatile при замере времени

C++ - volatile при замере времени

Есть вот такой вот код, замеряющий время работы трех разных функции умножения матриц и записывающий их в файл:

98
Передача string_view по ссылке или значению

Передача string_view по ссылке или значению

Как правильно передавать std::string_view в функцию, если не надо изменять строку?

179
Как компилировать быстрее?

Как компилировать быстрее?

Есть Incredibuild, но она вроде платная?

83