From f3559d133df9628971acfa26dc1b965e7435c3c4 Mon Sep 17 00:00:00 2001 From: wuyize Date: Sun, 12 Feb 2023 12:16:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=A4=A9=E7=A9=BA=E7=9B=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 6 +- ...rchitectureColoredPainting.vcxproj.filters | 12 + .../{res => }/HDRI/clarens_midday_4k.hdr | Bin .../res/MainWindow.qrc | 4 + .../res/Shaders/cubemap.frag | 22 ++ .../res/Shaders/cubemap.vert | 13 ++ .../res/Shaders/final.frag | 93 +------- .../res/Shaders/shadow_mapping.comp | 32 ++- .../res/Shaders/skybox.frag | 16 ++ .../res/Shaders/skybox.vert | 17 ++ .../src/Renderer/RendererGLWidget.cpp | 217 +++++++++++++++++- .../src/Renderer/RendererGLWidget.h | 2 + 12 files changed, 331 insertions(+), 103 deletions(-) rename ArchitectureColoredPainting/{res => }/HDRI/clarens_midday_4k.hdr (100%) create mode 100644 ArchitectureColoredPainting/res/Shaders/cubemap.frag create mode 100644 ArchitectureColoredPainting/res/Shaders/cubemap.vert create mode 100644 ArchitectureColoredPainting/res/Shaders/skybox.frag create mode 100644 ArchitectureColoredPainting/res/Shaders/skybox.vert diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 4276045..d90027e 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -72,7 +72,7 @@ FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions) - %(AdditionalDependencies) + opengl32.lib;%(AdditionalDependencies) @@ -154,6 +154,8 @@ + + @@ -170,6 +172,8 @@ + + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index c6c1dd9..be9f632 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -299,6 +299,18 @@ Resource Files\Shaders + + Resource Files\Shaders + + + Resource Files\Shaders + + + Resource Files\Shaders + + + Resource Files\Shaders + diff --git a/ArchitectureColoredPainting/res/HDRI/clarens_midday_4k.hdr b/ArchitectureColoredPainting/HDRI/clarens_midday_4k.hdr similarity index 100% rename from ArchitectureColoredPainting/res/HDRI/clarens_midday_4k.hdr rename to ArchitectureColoredPainting/HDRI/clarens_midday_4k.hdr diff --git a/ArchitectureColoredPainting/res/MainWindow.qrc b/ArchitectureColoredPainting/res/MainWindow.qrc index a653907..83a1414 100644 --- a/ArchitectureColoredPainting/res/MainWindow.qrc +++ b/ArchitectureColoredPainting/res/MainWindow.qrc @@ -24,6 +24,10 @@ darkstyle.qss lightstyle.qss Shaders/element.comp + Shaders/cubemap.frag + Shaders/cubemap.vert + Shaders/skybox.frag + Shaders/skybox.vert qt.conf diff --git a/ArchitectureColoredPainting/res/Shaders/cubemap.frag b/ArchitectureColoredPainting/res/Shaders/cubemap.frag new file mode 100644 index 0000000..8e9bd85 --- /dev/null +++ b/ArchitectureColoredPainting/res/Shaders/cubemap.frag @@ -0,0 +1,22 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform sampler2D equirectangularMap; + +const vec2 invAtan = vec2(0.1591, 0.3183); +vec2 SampleSphericalMap(vec3 v) +{ + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= invAtan; + uv += 0.5; + return uv; +} + +void main() +{ + vec2 uv = SampleSphericalMap(normalize(WorldPos)); + vec3 color = texture(equirectangularMap, uv).rgb; + + FragColor = vec4(color, 1.0); +} diff --git a/ArchitectureColoredPainting/res/Shaders/cubemap.vert b/ArchitectureColoredPainting/res/Shaders/cubemap.vert new file mode 100644 index 0000000..19dc4ef --- /dev/null +++ b/ArchitectureColoredPainting/res/Shaders/cubemap.vert @@ -0,0 +1,13 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +out vec3 WorldPos; + +uniform mat4 projection; +uniform mat4 view; + +void main() +{ + WorldPos = aPos; + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/res/Shaders/final.frag b/ArchitectureColoredPainting/res/Shaders/final.frag index d947ecf..312e431 100644 --- a/ArchitectureColoredPainting/res/Shaders/final.frag +++ b/ArchitectureColoredPainting/res/Shaders/final.frag @@ -70,90 +70,19 @@ void main() //FragColor = vec4(vec3(depth*10000),1); //FragColor = vec4(vec3(textureSize(gShadowMap, 0)-vec3(1)),1); //FragColor = vec4(texture(gRadiance, TexCoords).rgb, 1); - vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2)); - vec3 color = albedo * texture(gIndirectLight, TexCoords).rgb + texture(gDirectLight, TexCoords).rgb; + + //vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2)); + //vec3 color = albedo * texture(gIndirectLight, TexCoords).rgb + texture(gDirectLight, TexCoords).rgb; + vec4 rgbm = texture(gBaseColor, TexCoords); + if(rgbm.a==0) + { + //FragColor = vec4(1,0,0,1); + //return; + discard; + } + vec3 color = 8 * rgbm.rgb * rgbm.a; color = color / (color + vec3(1.0)); color = pow(color, vec3(1.0/2.2)); FragColor = vec4(color, 1.0); return; - - - - float metallic = texture(gMetallicRoughness, TexCoords).r; - float roughness = texture(gMetallicRoughness, TexCoords).g; - - - vec3 N = texture(gNormal, TexCoords).xyz; - vec3 WorldPos = texture(gPosition, TexCoords).xyz; - - if(N==vec3(0)) - { - vec3 color = mainLightRadiance; - - color = color / (color + vec3(1.0)); - color = pow(color, vec3(1.0/2.2)); - - FragColor = vec4(color, 1.0); - return; - } - - - vec3 V = normalize(camPos - WorldPos); - - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); - - // reflectance equation - vec3 Lo = vec3(0.0); - - - // calculate per-light radiance - vec3 L = normalize(mainLightDirection); - vec3 H = normalize(V + L); - //float distance = length(lightPositions[i] - WorldPos); - //float attenuation = 1.0 / (distance * distance); - vec3 radiance = mainLightRadiance ;//* attenuation; - - // cook-torrance brdf - float NDF = DistributionGGX(N, H, roughness); - float G = GeometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); - //F = clamp(F,vec3(0),vec3(1)); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 nominator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; - vec3 specular = nominator / denominator; - - // add to outgoing radiance Lo - float NdotL = max(dot(N, L), 0.0); - Lo += (kD * albedo / PI + specular) * radiance * NdotL; - - vec3 ambient = vec3(0.03) * albedo; - - - - //vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0); - //float bias = 0.08 * max(0.05 * (1.0 - dot(N, L)), 0.005); - //int debugLayer; - //float shadow = ShadowCalculation(WorldPos, N, debugLayer); - - //vec3 color = ambient + Lo; - //vec3 color = indirect*1; - float directLight = texture(gDirectLight, TexCoords).r; - color = ambient + directLight * Lo; - //color*=mix(mix(vec3(1,0,0), vec3(0,1,0), float(debugLayer)/shadowCascadeCount/0.5), - //mix(vec3(0,1,0), vec3(0,0,1), float(debugLayer)/(shadowCascadeCount)/0.5-1), float(debugLayer)/(shadowCascadeCount)); - //vec3 color = (1.0 - shadow) * Lo; - //vec3 color = (1.0 - shadow) * Lo + indirect*10; - color = color / (color + vec3(1.0)); - color = pow(color, vec3(1.0/2.2)); - - FragColor = vec4(color, 1.0); - //FragColor = vec4(vec3(shadow), 1); - //FragColor = vec4(texture(gShadowNormal, TexCoords).rgb, 1.0); - } \ No newline at end of file diff --git a/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp b/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp index 56741e5..f0b995f 100644 --- a/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp +++ b/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp @@ -2,7 +2,8 @@ layout (local_size_x = 8, local_size_y = 8) in; -uniform sampler2D gBaseColor; +layout(rgba8, binding = 0) uniform image2D gBaseColor; +//uniform sampler2D gBaseColor; uniform sampler2D gNormal; uniform sampler2D gPosition; uniform sampler2D gMetallicRoughness; @@ -132,11 +133,26 @@ float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer) return shadow; } +vec4 encodeRGBM(vec3 color) +{ + if(dot(color,color)==0) + return vec4(0,0,0,1); + vec4 rgbm; + float range = 8; + color /= range; + rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0); + rgbm.a = ceil(rgbm.a * 255.0) / 255.0; + rgbm.rgb = color / rgbm.a; + return rgbm; +} + void main() { ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); - vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + + //vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + vec3 albedo = pow(imageLoad(gBaseColor, pixelLocation).rgb, vec3(2.2)); float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r; float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g; @@ -145,12 +161,9 @@ void main() if(normal==vec3(0)) { - vec3 color = mainLightRadiance; - - //color = color / (color + vec3(1.0)); - //color = pow(color, vec3(1.0/2.2)); - - imageStore(gDirectLight, pixelLocation, vec4(color, 1.0)); + //vec3 color = mainLightRadiance; + //imageStore(gBaseColor, pixelLocation, vec4(color, 1.0)); + imageStore(gBaseColor, pixelLocation, vec4(0)); return; } @@ -187,5 +200,6 @@ void main() int debugLayer; float shadow = ShadowCalculation(worldPos, normal, debugLayer); - imageStore(gDirectLight, pixelLocation, vec4((1-shadow)*Lo, 1)); + vec3 color = (1-shadow)*Lo + albedo*0.03; + imageStore(gBaseColor, pixelLocation, encodeRGBM(color)); } \ No newline at end of file diff --git a/ArchitectureColoredPainting/res/Shaders/skybox.frag b/ArchitectureColoredPainting/res/Shaders/skybox.frag new file mode 100644 index 0000000..b2fde1e --- /dev/null +++ b/ArchitectureColoredPainting/res/Shaders/skybox.frag @@ -0,0 +1,16 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; + +void main() +{ + vec3 envColor = texture(environmentMap, WorldPos).rgb; + + // HDR tonemap and gamma correct + envColor = envColor / (envColor + vec3(1.0)); + envColor = pow(envColor, vec3(1.0/2.2)); + + FragColor = vec4(envColor, 1.0); +} diff --git a/ArchitectureColoredPainting/res/Shaders/skybox.vert b/ArchitectureColoredPainting/res/Shaders/skybox.vert new file mode 100644 index 0000000..f2d2cbb --- /dev/null +++ b/ArchitectureColoredPainting/res/Shaders/skybox.vert @@ -0,0 +1,17 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +uniform mat4 projection; +uniform mat4 view; + +out vec3 WorldPos; + +void main() +{ + WorldPos = aPos; + + mat4 rotView = mat4(mat3(view)); + vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0); + + gl_Position = clipPos.xyww; +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp index e40e7ee..374b4f9 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp @@ -6,6 +6,10 @@ #include #include #include +#include +#define STB_IMAGE_IMPLEMENTATION +#include + using namespace Renderer; //QVector3D lightPositions[] = { 2000 * QVector3D(0.2, 4, 1).normalized(), QVector3D(100,100,100) ,QVector3D(-100,100,100) ,QVector3D(100,100,-100) }; QVector3D lightColors[] = { 20 * QVector3D(0.7529,0.7450,0.6784).normalized(), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) }; @@ -89,13 +93,180 @@ void RendererGLWidget::setMainLightYaw(float yaw) sunYaw = yaw; } QOpenGLTexture randomMap(QOpenGLTexture::Target2D); + +void renderCube(QOpenGLFunctions_4_5_Compatibility* glFunc) +{ + static GLuint cubeVAO = 0, cubeVBO = 0; + // initialize (if necessary) + if (cubeVAO == 0) + { + float vertices[] = { + // back face + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left + // front face + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + // left face + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + // right face + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left + // bottom face + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + // top face + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left + }; + glFunc->glGenVertexArrays(1, &cubeVAO); + glFunc->glGenBuffers(1, &cubeVBO); + // fill buffer + glFunc->glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glFunc->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + // link vertex attributes + glFunc->glBindVertexArray(cubeVAO); + glFunc->glEnableVertexAttribArray(0); + glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glFunc->glEnableVertexAttribArray(1); + glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glFunc->glEnableVertexAttribArray(2); + glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glFunc->glBindBuffer(GL_ARRAY_BUFFER, 0); + glFunc->glBindVertexArray(0); + } + // render Cube + glFunc->glBindVertexArray(cubeVAO); + glFunc->glDrawArrays(GL_TRIANGLES, 0, 36); + glFunc->glBindVertexArray(0); +} + +GLuint generateCubemap(QOpenGLFunctions_4_5_Compatibility* glFunc) +{ + QOpenGLShaderProgram shader; + if (!shader.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/cubemap.vert")) + qDebug() << "ERROR:" << shader.log(); + if (!shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/cubemap.frag")) + qDebug() << "ERROR:" << shader.log(); + if (!shader.link()) + qDebug() << "ERROR:" << shader.log(); + // pbr: setup framebuffer + // ---------------------- + unsigned int captureFBO; + unsigned int captureRBO; + glFunc->glGenFramebuffers(1, &captureFBO); + glFunc->glGenRenderbuffers(1, &captureRBO); + + glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); + glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 1024, 1024); + glFunc->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO); + + // pbr: load the HDR environment map + // --------------------------------- + stbi_set_flip_vertically_on_load(true); + int width, height, nrComponents; + float* data = stbi_loadf("HDRI/clarens_midday_4k.hdr", &width, &height, &nrComponents, 0); + unsigned int hdrTexture; + if (data) + { + glGenTextures(1, &hdrTexture); + glBindTexture(GL_TEXTURE_2D, hdrTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, data); + + 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_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + stbi_image_free(data); + } + else + std::cout << "Failed to load HDR image." << std::endl; + + // pbr: setup cubemap to render to and attach to framebuffer + // --------------------------------------------------------- + unsigned int envCubemap; + glFunc->glGenTextures(1, &envCubemap); + glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); + for (unsigned int i = 0; i < 6; ++i) + { + glFunc->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 512, 512, 0, GL_RGB, GL_FLOAT, nullptr); + } + glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // pbr: set up projection and view matrices for capturing data onto the 6 cubemap face directions + // ---------------------------------------------------------------------------------------------- + QMatrix4x4 captureProjection; + captureProjection.perspective(90.0f, 1.0f, 0.1f, 10.0f); + + QMatrix4x4 captureViews[6]; + captureViews[0].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D( 1.0f, 0.0f, 0.0f), QVector3D(0.0f, -1.0f, 0.0f)); + captureViews[1].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(-1.0f, 0.0f, 0.0f), QVector3D(0.0f, -1.0f, 0.0f)); + captureViews[2].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D( 0.0f, 1.0f, 0.0f), QVector3D(0.0f, 0.0f, 1.0f)); + captureViews[3].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D( 0.0f, -1.0f, 0.0f), QVector3D(0.0f, 0.0f, -1.0f)); + captureViews[4].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D( 0.0f, 0.0f, 1.0f), QVector3D(0.0f, -1.0f, 0.0f)); + captureViews[5].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D( 0.0f, 0.0f, -1.0f), QVector3D(0.0f, -1.0f, 0.0f)); + + // pbr: convert HDR equirectangular environment map to cubemap equivalent + // ---------------------------------------------------------------------- + shader.bind(); + shader.setUniformValue("equirectangularMap", 0); + shader.setUniformValue("projection", captureProjection); + glFunc->glActiveTexture(GL_TEXTURE0); + glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture); + + glFunc->glViewport(0, 0, 512, 512); // don't forget to configure the viewport to the capture dimensions. + glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + for (unsigned int i = 0; i < 6; ++i) + { + shader.setUniformValue("view", captureViews[i]); + glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0); + glFunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderCube(glFunc); + } + glFunc->glBindFramebuffer(GL_FRAMEBUFFER, 0); + return envCubemap; +} + + void RendererGLWidget::initializeGL() { initializeOpenGLFunctions(); qDebug() << "GL_VERSION" << (char*)glGetString(GL_VERSION); glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); + glDepthFunc(GL_LEQUAL); glClearColor(0, 0, 0, 1); shadowProgramPtr = new QOpenGLShaderProgram; @@ -162,6 +333,13 @@ void RendererGLWidget::initializeGL() if (!finalProgramPtr->link()) qDebug() << "ERROR:" << finalProgramPtr->log(); + skyBoxProgramPtr = new QOpenGLShaderProgram; + if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/skybox.vert")) + qDebug() << "ERROR:" << skyBoxProgramPtr->log(); + if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/skybox.frag")) + qDebug() << "ERROR:" << skyBoxProgramPtr->log(); + if (!skyBoxProgramPtr->link()) + qDebug() << "ERROR:" << skyBoxProgramPtr->log(); shadowProgramPtr->bind(); glGenBuffers(1, &lightSpaceMatricesUBO); @@ -177,7 +355,7 @@ void RendererGLWidget::initializeGL() depthInitProgramPtr->release(); shadowMappingProgramPtr->bind(); - shadowMappingProgramPtr->setUniformValue("gBaseColor", 0); + //shadowMappingProgramPtr->setUniformValue("gBaseColor", 0); shadowMappingProgramPtr->setUniformValue("gNormal", 1); shadowMappingProgramPtr->setUniformValue("gPosition", 2); shadowMappingProgramPtr->setUniformValue("gMetallicRoughness", 3); @@ -229,6 +407,11 @@ void RendererGLWidget::initializeGL() paintingHelper = new PaintingHelper(QOpenGLContext::currentContext()->versionFunctions()); model = new Model(context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper); + skyBoxProgramPtr->bind(); + skyBoxProgramPtr->setUniformValue("environmentMap", 0); + skyBoxProgramPtr->release(); + skyCubemap = generateCubemap(QOpenGLContext::currentContext()->versionFunctions()); + quadVAO.create(); QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); @@ -259,6 +442,7 @@ void RendererGLWidget::initializeGL() void RendererGLWidget::paintGL() { + glEnable(GL_CULL_FACE); light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw))); light.lightDirection.setY(sin(qDegreesToRadians(sunPitch))); @@ -266,13 +450,13 @@ void RendererGLWidget::paintGL() light.lightDirection.normalize(); const std::vector lightMatrices = light.getLightSpaceMatrices(); - //qDebug() << lightMatrices; glBindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO); for (size_t i = 0; i < lightMatrices.size(); i++) { glBufferSubData(GL_UNIFORM_BUFFER, i * 16 * sizeof(GLfloat), 16 * sizeof(GLfloat), lightMatrices[i].data()); } glBindBuffer(GL_UNIFORM_BUFFER, 0); + { glBindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle); glViewport(0, 0, shadowMapResolution, shadowMapResolution); @@ -303,7 +487,6 @@ void RendererGLWidget::paintGL() if (model != nullptr) model->draw(); - fboPtr->release(); } @@ -350,8 +533,8 @@ void RendererGLWidget::paintGL() shadowMappingProgramPtr->setUniformValue("camPos", camera.Position); shadowMappingProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); shadowMappingProgramPtr->setUniformValue("mainLightRadiance", lightColors[0]); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, gbuffers[0]); + /*glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, gbuffers[0]);*/ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gbuffers[1]); glActiveTexture(GL_TEXTURE2); @@ -360,11 +543,12 @@ void RendererGLWidget::paintGL() glBindTexture(GL_TEXTURE_2D, gbuffers[3]); glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer); + glBindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); glBindImageTexture(1, gbuffers[8], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); glDispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); shadowMappingProgramPtr->release(); - ssgiProgramPtr->bind(); + /*ssgiProgramPtr->bind(); ssgiProgramPtr->setUniformValue("camPos", camera.Position); ssgiProgramPtr->setUniformValue("cameraMatrix", projection * view); ssgiProgramPtr->setUniformValue("projectionMatrix", projection); @@ -386,11 +570,11 @@ void RendererGLWidget::paintGL() glBindTexture(GL_TEXTURE_2D, gbuffers[8]); glBindImageTexture(1, gbuffers[9], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); glDispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); - ssgiProgramPtr->release(); + ssgiProgramPtr->release();*/ glViewport(0, 0, frameWidth, frameHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); + //QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); finalProgramPtr->bind(); /*finalProgramPtr->setUniformValue("camPos", camera.Position); finalProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); @@ -410,10 +594,21 @@ void RendererGLWidget::paintGL() //glActiveTexture(GL_TEXTURE4); //glBindTexture(GL_TEXTURE_2D, gbuffers[7]); //glActiveTexture(GL_TEXTURE5); - //glBindTexture(GL_TEXTURE_2D, gbuffers[8]); + //glBindTexture(GL_TEXTURE_2D, gbuffers[8]); + quadVAO.bind(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + quadVAO.release(); finalProgramPtr->release(); + skyBoxProgramPtr->bind(); + glDisable(GL_CULL_FACE); + skyBoxProgramPtr->setUniformValue("view", view); + skyBoxProgramPtr->setUniformValue("projection", projection); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, skyCubemap); + renderCube(QOpenGLContext::currentContext()->versionFunctions()); + skyBoxProgramPtr->release(); + GLuint paintingCompDuration; glGetQueryObjectuiv(paintingCompQuery, GL_QUERY_RESULT, &paintingCompDuration); @@ -427,7 +622,7 @@ void RendererGLWidget::paintGL() if (accTime > 1.) { std::cout << std::format("{:20}\r", ""); - std::cout << std::format("FPS: {:.2f} Painting: {}ms Pos: {},{},{}\r", frameCnt / accTime, paintingCompDuration/1e6, camera.Position.x(), camera.Position.y(), camera.Position.z()); + std::cout << std::format("FPS: {:.2f} Painting: {}ms Pos: {},{},{}\r", frameCnt / accTime, paintingCompDuration / 1e6, camera.Position.x(), camera.Position.y(), camera.Position.z()); //std::cout << "FPS: " << frameCnt / accTime << " " << camera.Position.x() << " " << camera.Position.y() << " " << camera.Position.z() << "\r"; accTime = 0; frameCnt = 0; diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h index 1b1caef..ec1fee8 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h @@ -57,11 +57,13 @@ namespace Renderer QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr; QOpenGLShaderProgram* ssgiProgramPtr = nullptr; QOpenGLShaderProgram* finalProgramPtr = nullptr; + QOpenGLShaderProgram* skyBoxProgramPtr = nullptr; QOpenGLFramebufferObject* fboPtr = nullptr; GLuint gbuffers[10]; GLuint shadowFboHandle = 0; GLuint shadowGbuffer; GLuint lightSpaceMatricesUBO; + GLuint skyCubemap; QOpenGLBuffer quadVBO; QOpenGLVertexArrayObject quadVAO; Model* model = nullptr;