Я следую этому учебнику по эффекту цветения.
Я работаю с Qt , и сцена, которую я пытаюсь визуализировать, состоит изпять кубов и пять источников света расположены случайным образом, что-то вроде этоготолько цвет фона).
Это соответствующие части кода.
метод initializeGL :
void initializeGL()
{
initializeOpenGLFunctions();
// ...
// hdr framebuffer
glGenFramebuffers(1, &(FBOs[0]));
glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]);
glGenTextures(2, &(textures[0]));
for (int i = 0; i < 2; i++)
{
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, geometry().width(), geometry().height(), 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0);
}
GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, geometry().width(), geometry().height());
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, attachments);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
qDebug() << "framebuffer NOT complete";
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
метод paintGL:
void paintGL()
{
view.setToIdentity();
view.lookAt(camera.eye, camera.center, camera.up);
glClearColor(background.redF(), background.greenF(), background.blueF(), background.alphaF());
glEnable(GL_DEPTH_TEST);
// draw scene
glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (auto position : positions)
{
drawCube(position);
}
for (auto light : lights)
{
drawLightMarker(light);
}
// draw frame
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawQuad();
// draw next frame
update();
}
метод drawQuad :
void drawQuad()
{
GLuint* vao = &VAOs[BLOOM];
if (*vao == 0)
{
glGenVertexArrays(1, vao);
float l = 1.0f;
QVector2D LD(-l, -l); // left-down
QVector2D LU(-l, +l); // left-up
QVector2D RD(+l, -l); // right-down
QVector2D RU(+l, +l); // right-up
QVector<QVector2D> vertices = { LD, RD, LU, LU, RD, RU };
QVector<QVector2D> texcoords;
for (auto v : vertices)
{
texcoords += (v + QVector2D(l, l)) / (2.0f * l);
}
// bind vao
glBindVertexArray(*vao);
// vertices
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(QVector2D), &(vertices[0]), GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(QVector2D), static_cast<void*>(nullptr));
glEnableVertexAttribArray(0);
// texcoords
GLuint tbo;
glGenBuffers(1, &tbo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, texcoords.size()*sizeof(QVector2D), &(texcoords[0]), GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(QVector2D), static_cast<void*>(nullptr));
glEnableVertexAttribArray(1);
// unbind buffer object
glBindBuffer(GL_ARRAY_BUFFER, 0);
// unbind vao
glBindVertexArray(0);
}
GLuint program = programs[BLOOM];
glUseProgram(program);
glUniform1i(glGetUniformLocation(program, "scene"), 0);
glUniform1i(glGetUniformLocation(program, "bloom"), 1);
glUniform1i(glGetUniformLocation(program, "effect"), true);
glBindVertexArray(*vao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
фрагментный шейдер кубов :
#version 450 core
layout (location = 0) out vec4 pixel;
layout (location = 1) out vec4 bloom;
struct Material
{
// material properties
};
uniform Material material;
struct Light
{
// light properties
};
uniform Light[5] lights;
uniform vec3 eye;
in FragData
{
vec3 position;
vec3 normal;
} data;
vec3 point(Light light, vec3 position, vec3 normal, vec3 eye)
{
// lighting computation
}
void main()
{
vec3 color = vec3(0.0f);
for (int i = 0; i < 5; i++)
{
color += point(lights[i], data.position, data.normal, eye);
}
pixel = vec4(color, 1.0f);
vec3 weights = vec3(0.2126f, 0.7152f, 0.0722f);
float brightness = dot(pixel.rgb, weights);
if (brightness > 1.0f)
{
bloom = vec4(pixel.rgb, 1.0f);
}
else
{
bloom = vec4(vec3(0.0f), 1.0f);
}
}
световой маркер фрагмента шейдера :
#version 450 core
layout (location = 0) out vec4 pixel;
layout (location = 1) out vec4 bloom;
struct Light
{
// light properties
};
uniform Light light;
void main()
{
pixel = vec4(light.diffuse, 1.0f);
vec3 weights = vec3(0.2126f, 0.7152f, 0.0722f);
float brightness = dot(pixel.rgb, weights);
if (brightness > 1.0f)
{
bloom = vec4(light.diffuse, 1.0f);
}
else
{
bloom = vec4(vec3(0.0f), 1.0f);
}
}
конечный вершинный шейдер :
#version 450 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 texcoord;
out FragData
{
vec2 texcoord;
} data;
void main()
{
data.texcoord = texcoord;
gl_Position = vec4(position, 0.0f, 1.0f);
}
финальный фрагментный шейдер :
#version 450 core
in FragData
{
vec2 texcoord;
} data;
out vec4 pixel;
uniform sampler2D scene;
uniform sampler2D bloom;
uniform bool effect;
void main()
{
vec3 hdr = texture(scene, data.texcoord).rgb;
if (effect)
{
hdr += texture(bloom, data.texcoord).rgb;
}
// tone mapping
float exposure = 1.0f;
pixel = vec4(vec3(1.0f) - exp(-hdr * exposure), 1.0f);
// gamma correction
float gamma = 2.2f;
pixel = vec4(pow(pixel.rgb, vec3(1.0 / gamma)), 1.0f);
}
В данный момент я еще не реализовал размытие, чтобы получить эффект цветения, но я просто извлек два изображения из отрисованной сцены и добавил их вместе.
Где я делаю не так?Большое спасибо за вашу помощь!