Отложенный рендеринг не работает должным образом
Я довольно опытный с opengl и GLSL. Для моего двигателя я хотел реализовать отложенное освещение, зная, что это не будет тривиальной задачей. Через несколько часов я смог заставить вещи работать в основном. Вот скриншот всех буферов, которые я рендерил:
Верхний левый угол - нормали, верхний правый - альбедо, нижний левый - позиция, а нижний правый - окончательный рендер. (Сейчас только один источник света визуализируется.) Я использую различные шейдеры для рендеринга всех вещей в буфер кадров. Ранее я использовал шейдер освещения для рендеринга. Мы надеемся, что для получения одинаковых результатов я использовал те же данные из этого вершинного шейдера для визуализации разных буферов. Источник света перемещается и изменяется в зависимости от положения моей камеры, в отличие от моего рендера. Вот код для вершинных шейдеров (фрагменты просто отображают пиксели, которые они получили от вершинного)
Положение шейдера:
varying vec4 pos;
void main(void)
{
gl_Position =gl_ModelViewProjectionMatrix*gl_Vertex;
pos = gl_ModelViewMatrix*gl_Vertex;
}
Нормальный шейдер
varying vec3 normal;
void main(void)
{
gl_Position =gl_ModelViewProjectionMatrix*gl_Vertex;
normal = normalize(gl_NormalMatrix*gl_Normal);
}
Для альбедо я просто использую обычный шейдер opengl и просто связываю текстуры.
Вот последний световой шейдер, который отображается на экране в виде четырехугольника:
uniform sampler2D positionMap;
uniform sampler2D normalMap;
uniform sampler2D albedoMap;
varying vec2 texcoord;
uniform mat4 matrix;
void main()
{
vec3 position = vec3(texture2D(positionMap,texcoord));
vec3 normal = vec3(texture2D(normalMap,texcoord));
vec3 L = normalize(gl_LightSource[0].position.xyz - position);
float l = length(L)/5.0;
float att = 1.0/(l*l+l);
//render sun light
vec4 diffuselight = max(dot(normal,L), 0.0)*vec4(att,att,att,att);
diffuselight = clamp(diffuselight, 0.0, 1.0)*2.0;
vec4 amb = vec4(.2,.2,.2,0);
vec4 texture = texture2D(albedoMap,texcoord);
gl_FragColor = ((diffuselight)+amb)*texture;
}
У этого есть много функций, на которые ссылаются в другом месте, но я думаю, что вы можете получить общую основу из рисунков и кода. Это основная функция рендеринга:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//render skybox
glLoadIdentity();
renderSkybox();
//skybox.renderObject();
glLoadIdentity();
renderViewModel();
renderCamera();
glMatrixMode(GL_MODELVIEW);
GLfloat position[] = {-Lighting.x,-Lighting.y,-Lighting.z,1};
glLightfv(GL_LIGHT0, GL_POSITION, position);
glDisable(GL_LIGHTING);
glm::mat4 modelView,projection,final;
glGetFloatv(GL_MODELVIEW_MATRIX, &modelView[0][0]);
glGetFloatv(GL_PROJECTION_MATRIX, &projection[0][0]);
final=modelView*projection;
Lighting.setupDepthImage();
glLoadIdentity();
for (int i = 0; i < objects.size(); i++)
{
objects[i].renderObjectForDepth();
}
Lighting.finishDepthImage();
//render the 3 buffers
//normal buffer
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Normal.frameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < objects.size(); i++)
{
objects[i].renderObjectWithProgram(Lighting.normalShader);
}
//albedo
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Albedo.frameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < objects.size(); i++)
{
objects[i].renderObjectWithProgram(0);
}
//position
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Position.frameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < objects.size(); i++)
{
objects[i].renderObjectWithProgram(Lighting.positionShader);
}
//go back to rendering directly to the screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
renderCamera();
glTranslatef(-test.position.x, test.position.y, -test.position.z);
test.updateParticle(1);
//render the buffers for debugging
renderViewModel();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1280, 800, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//render the full screen quad for the sun
glUseProgram(Lighting.sunShader);
glUniform1i(glGetUniformLocation(Lighting.sunShader,"normalMap"),0);
glUniform1i(glGetUniformLocation(Lighting.sunShader,"albedoMap"),1);
glUniform1i(glGetUniformLocation(Lighting.sunShader,"positionMap"),2);
glUniformMatrix4fv(glGetUniformLocation(Lighting.sunShader, "matrix"), 1, GL_FALSE, &final[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Lighting.Normal.texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, Lighting.Albedo.texture);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Lighting.Position.texture);
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.debugFinal.frameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(0, 0);
glTexCoord2f(1, 1);
glVertex2f(1280, 0);
glTexCoord2f(1, 0);
glVertex2f(1280, 800);
glTexCoord2f(0, 0);
glVertex2f(0, 800);
glEnd();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
//normals
glBindTexture(GL_TEXTURE_2D,Lighting.Normal.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(0, 0);
glTexCoord2f(1, 1);
glVertex2f(640, 0);
glTexCoord2f(1, 0);
glVertex2f(640, 400);
glTexCoord2f(0, 0);
glVertex2f(0, 400);
glEnd();
//albedo
glBindTexture(GL_TEXTURE_2D,Lighting.Albedo.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(640, 0);
glTexCoord2f(1, 1);
glVertex2f(1280, 0);
glTexCoord2f(1, 0);
glVertex2f(1280, 400);
glTexCoord2f(0, 0);
glVertex2f(640, 400);
glEnd();
//position
glBindTexture(GL_TEXTURE_2D,Lighting.Position.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(0, 400);
glTexCoord2f(1, 1);
glVertex2f(640, 400);
glTexCoord2f(1, 0);
glVertex2f(640, 800);
glTexCoord2f(0, 0);
glVertex2f(0, 800);
glEnd();
//final image
glBindTexture(GL_TEXTURE_2D,Lighting.debugFinal.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(640, 400);
glTexCoord2f(1, 1);
glVertex2f(1280, 400);
glTexCoord2f(1, 0);
glVertex2f(1280, 800);
glTexCoord2f(0, 0);
glVertex2f(640, 800);
glEnd();
View3D();
SDL_GL_SwapWindow(window);
glLoadIdentity();
Здесь есть несколько не связанных вещей, просто игнорируйте их. Как вы видели, я получаю положение источника света, используя метод GLSL по умолчанию. Я думаю, что, поскольку я нахожусь в орфографическом виде, что-то не так с положением света Может ли это быть проблемой, или есть что-то еще, возможно, в расчете нормалей и т. Д.?
1 ответ
Люди, вероятно, не найдут это полезным, но я решил свою проблему. Я использовал обычные огни opengl для освещения в шейдере. Когда я установил положение, я сделал значение w 1, что сделало бы его направленным источником света, а не точечным источником света, и, следовательно, дал поведение движения света.
Как сторона, я не изменил позицию для восстановления из буфера глубины, а также несколько других вещей для улучшения G-буфера.