SSAO работает, но имеет странное наложение красного цвета
Ssao работает, но есть странное наложение красного цвета из-за того, что ssao использует только красный канал, конечно, это показано на рисунке ниже.
Однако когда я делаю glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); красный цвет идет, но ssao идет также.
Результат после выполнения glClear(). Нет SSAO больше
Вот весь код, который вам нужен...
// ------------------------------ LIGHT PASS -------------------------------- //
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaders[LIGHT_PASS]->UseProgram(); // Bind light pass shader
// Parse the camera position
LightPass::Render(Content::_map->GetCamera(), Content::_map->GetCamera()->GetPosition());
GBuffer::Render(); // bind the gbuffer textures (includes SSAO)
renderQuad(); // Render the screen rectangle
// -------------------------------------------------------------------- //
Геометрический код доступа..
// ----------------------------- GEOMETRY PASS ----------------------------- //
GBuffer::Bind(); // Bind the world gbuffer frame buffer
shaders[GEOMETRY_PASS]->UseProgram(); // Bind geometry shader
GeometryPass::Render(); // Render geometry
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind the gbuffer
// --------------------------------------------------------------------- //
Код доступа SSAO..
static inline void Initialise(unsigned int ssao_program, unsigned int ssaoblur_program)
{
program = ssao_program;
program2 = ssaoblur_program;
// SSAO color fbo
glGenTextures(1, &ssaoColorBuffer);
glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1920, 1080, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBuffer, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "SSAO Framebuffer not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// blur fbo
glGenFramebuffers(1, &ssaoBlurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO);
// SSAO color buffer
glGenTextures(1, &ssaoColorBufferBlur);
glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1920, 1080, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBufferBlur, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "SSAO Framebuffer not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
std::uniform_real_distribution<GLfloat> randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0
std::default_random_engine generator;
for (unsigned int i = 0; i < 64; ++i)
{
glm::vec3 sample(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, randomFloats(generator));
sample = glm::normalize(sample);
sample *= randomFloats(generator);
float scale = float(i) / 64.0;
// scale samples s.t. they're more aligned to center of kernel
scale = lerp(0.1f, 1.0f, scale * scale);
sample *= scale;
ssaoKernel.push_back(sample);
}
for (unsigned int i = 0; i < 16; i++)
{
glm::vec3 noise(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, 0.0f); // rotate around z-axis (in tangent space)
ssaoNoise.push_back(noise);
}
glGenTextures(1, &noiseTexture);
glBindTexture(GL_TEXTURE_2D, noiseTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glUseProgram(ssao_program);
glUniform1i(glGetUniformLocation(ssao_program, "gPosition"), 0); // the positions texture in the gbuffer
glUniform1i(glGetUniformLocation(ssao_program, "gNormal"), 1); // the normals texture in the gbuffer
glUniform1i(glGetUniformLocation(ssao_program, "texNoise"), 2); // the albedospec texture within the gbuffe
glUseProgram(ssaoblur_program);
glUniform1i(glGetUniformLocation(ssaoblur_program, "ssaoInput"), 0); // the positions texture in the gbuffer
}
static inline void Render(Camera* _camera)
{
// generate SSAO texture
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
for (unsigned int i = 0; i < 64; ++i)
glUniform3fv(glGetUniformLocation(program, ("samples[" + std::to_string(i) + "]").c_str()), 1, glm::value_ptr(ssaoKernel[i]));
glUniformMatrix4fv(glGetUniformLocation(program, "proj"), 1, GL_FALSE, glm::value_ptr(_camera->GetProjectionMatrix()));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, GBuffer::GetPositions());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, GBuffer::GetNormals());
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, noiseTexture);
renderQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Blur ssao texture
glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program2);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer);
renderQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
GBuffer вершинный шейдер..
#version 420 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 texcoord;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec3 tangent;
out vec3 _texcoord;
out vec3 _normal;
out vec3 _tangent;
out vec3 _frag_pos;
uniform mat4 mod;
uniform mat4 view;
uniform mat4 proj;
void main()
{
vec4 view_space = view * mod * vec4(position, 1.0);
_frag_pos = view_space.xyz;
_texcoord = texcoord;
_normal = ((view * mod) * vec4(normal, 0.0)).xyz;
_tangent = (mod * vec4(tangent, 0.0)).xyz;
gl_Position = proj * view_space;
}
GBuffer фрагмент шейдера...
#version 420 core
layout(location = 0) out vec3 gPosition; // Position texel colour
layout(location = 1) out vec3 gNormal; // Normal texel colour
layout(location = 2) out vec4 gAlbedo; // Albedo texel colour
layout(location = 3) out vec3 gSpecular; // Cubemap texel colour
layout(location = 4) out vec3 gMetalness; // Cubemap texel colour
in vec3 _texcoord;
in vec3 _normal;
in vec3 _tangent;
in vec3 _frag_pos;
uniform vec3 camera_pos;
uniform sampler2D normal; // Normal map
uniform sampler2D albedo; // Albedo and specular map
uniform sampler2D specular; // Specular map
uniform sampler2D metalness; // Metalness map
uniform samplerCube cubemap; // Local cubemap reflection sampler
vec3 TBN()
{
vec3 Normal = normalize(_normal); // Optimise normal
vec3 Tangent = normalize(_tangent); // Optimise tangent
vec3 Bitangent = cross(Tangent, Normal); // Calculate bitangent
vec3 BumpMapNormal = texture(normal, vec2(_texcoord).st).rgb; // Assign rgb values from normal map
BumpMapNormal = 2.0 * BumpMapNormal - vec3(1.0, 1.0, 1.0); // normalise the normal map between -1 to 1
mat3 TBN = mat3(Tangent, Bitangent, Normal); // Create tangent, bitangent and normal matrix
vec3 NewNormal; // Create a new normal variable
NewNormal = TBN * vec3(BumpMapNormal.r, -BumpMapNormal.g, BumpMapNormal.b); // Flip green component for OpenGL
NewNormal = normalize(NewNormal); // Normalise the new normal
return NewNormal; // Return the newly calculated normal
}
vec4 Convolute()
{
vec4 result = vec4(0.0);
const float kernel[] = float[25] ( 0,1,2,1,0,
1,2,3,2,1,
2,3,4,3,2,
1,2,3,2,1,
0,1,2,1,0);
vec2 delta = 1.0 / textureSize(albedo, 0);
int index = 24;
for (int j = -1; j <= 1; j++)
{
for (int i = -1; i <= 1; i++)
{
//for (int k = -1; k <= 1; k++)
result += kernel[index--] * texture(albedo, vec2(_texcoord).st + (vec2(i, j) * delta));
}
}
result /= 25.0;
return result;
}
void main()
{
gPosition = _frag_pos;
gNormal = normalize(TBN());
vec3 I = normalize(_frag_pos - camera_pos); // Calculate eye to fragment direction
vec3 R = reflect(I, normalize(TBN())); // Reflect I with the vertex normal
float M = texture(metalness, vec2(_texcoord.st)).r;
//vec4 gaussian = Convolute();
gAlbedo = texture(albedo, vec2(_texcoord.st)); // Assign albedo
gSpecular = texture(specular, vec2(_texcoord.st)).rgb; // Assign specular
gMetalness = (texture(cubemap, R).rgb) * M; // Assign metalness
}
легкий шейдер...
#version 420 core
out vec4 FragColor;
in vec2 _texcoord;
uniform vec3 camera_pos;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedo;
uniform sampler2D gSpecular;
uniform sampler2D gMetalness;
uniform sampler2D gSsao;
uniform vec3 lightPos;
void main(void)
{
vec3 FragPos = texture(gPosition, _texcoord).rgb;
vec3 Normal = texture(gNormal, _texcoord).rgb;
vec3 Diffuse = texture(gAlbedo, _texcoord).rgb;
float Emissive = texture(gAlbedo, _texcoord).a;
vec3 Specular = texture(gAlbedo, _texcoord).rgb;
vec3 Metalness = texture(gMetalness, _texcoord).rgb; // Reflection pass
float AmbientOcclusion = texture(gSsao, _texcoord).r;
vec3 light_colour = vec3(1.0f, 0.8, 0.7);
vec3 lighting = vec3(0.3 * Diffuse * AmbientOcclusion);
vec3 viewDir = normalize(-FragPos);
vec3 lightDir = normalize(lightPos - FragPos);
vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * light_colour; // Light colour
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(Normal, halfwayDir), 0.0), 32.0);
vec3 specular = (Specular * light_colour) * spec;
vec3 metalness = Metalness * Diffuse;
lighting += diffuse + specular + metalness;
FragColor = vec4(lighting, 1.0);
}
Любой код нужно просто спросить. спасибо за любую помощь
РЕДАКТИРОВАТЬ Проблема исправлена, из-за отражения кубической карты, все работает
1 ответ
Если текстура ищется, а конкретный канал текстуры отсутствует в текстуре, то функция texture
вернет 0.0 для зеленого и синего каналов и 1.0 для альфа-канала.
Это может быть изменено параметрами текстуры Swizzle GL_TEXTURE_SWIZZLE_R
, GL_TEXTURE_SWIZZLE_G
, GL_TEXTURE_SWIZZLE_B
а также GL_TEXTURE_SWIZZLE_A
,
Если вы хотите, чтобы зеленый и синий каналы возвращали то же значение, что и красный канал, то это можно сделать так:
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED );
Примените эти параметры к объектам текстуры ssaoColorBuffer
а также ssaoColorBufferBlur
, чтобы решить вопрос.
См. Спецификацию основного профиля API OpenGL 4.6; 15,2. ШЕЙДЕР ИСПОЛНЕНИЕ; страница 487 ]:
Когда поиск текстуры выполняется в фрагментном шейдере, GL вычисляет значение отфильтрованной текстуры... и преобразует его в базовый цвет текстуры Cb, как показано в таблице 15.1,
Texture Base Texture base color Internal Format Cb Ab RED (Rt, 0, 0) 1 RG (Rt, Gt, 0) 1 RGB (Rt, Gt, Bt) 1 RGBA (Rt, Gt, Bt) At
Таблица 15.1. Соответствие отфильтрованных компонентов текстуры базовым компонентам текстуры.
с последующим переворотом компонентов Cb, контролируемых значениями параметров текстуры
TEXTURE_SWIZZLE_R
,TEXTURE_SWIZZLE_G
,TEXTURE_SWIZZLE_B
, а такжеTEXTURE_SWIZZLE_A
, Если значениеTEXTURE_SWIZZLE_R
обозначается swizzler, swizzling вычисляет первый компонент Cs в соответствии сif (swizzler == RED) Cs[0] = Cb[0]; else if (swizzler == GREEN) Cs[0] = Cb[1]; else if (swizzler == BLUE) Cs[0] = Cb[2]; else if (swizzler == ALPHA) Cs[0] = Ab; else if (swizzler == ZERO) Cs[0] = 0; else if (swizzler == ONE) Cs[0] = 1; // float or int depending on texture component type