Долгое время воевал один с этой задачей, но больше сил нет. Простая задача - объединить две (или более) картинки в одну, чтобы наложить на эту общую шейдер.
Вообще всё началось с того, что свет накладывается отдельной картинкой, но шейдеры почему-то не учитывают положение на экране и применяют эффект к центру.
На чём остановился сейчас:
Функция для создания фреймбуффера
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 );
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Есть вот такой вот код, замеряющий время работы трех разных функции умножения матриц и записывающий их в файл:
Как правильно передавать std::string_view в функцию, если не надо изменять строку?