From ef88c4a39efd9ec9ff11a56a63b74116480aa133 Mon Sep 17 00:00:00 2001 From: wuyize Date: Mon, 13 Feb 2023 23:14:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E8=AE=A1=E7=AE=97Br?= =?UTF-8?q?dfLut=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../res/Shaders/brdf_lut.comp | 2 +- .../res/Shaders/model.frag | 1 - .../res/Shaders/shader.frag | 140 ++---------------- .../res/Shaders/shadow_mapping.comp | 12 +- .../src/Renderer/IblUtils.cpp | 96 ++++++++++++ .../src/Renderer/IblUtils.h | 3 + .../src/Renderer/RendererGLWidget.cpp | 33 +++++ .../src/Renderer/RendererGLWidget.h | 1 + 8 files changed, 156 insertions(+), 132 deletions(-) diff --git a/ArchitectureColoredPainting/res/Shaders/brdf_lut.comp b/ArchitectureColoredPainting/res/Shaders/brdf_lut.comp index 651b12f..b52ac90 100644 --- a/ArchitectureColoredPainting/res/Shaders/brdf_lut.comp +++ b/ArchitectureColoredPainting/res/Shaders/brdf_lut.comp @@ -110,7 +110,7 @@ vec2 IntegrateBRDF(float NdotV, float roughness) void main() { uvec2 pixelLocation = gl_GlobalInvocationID.xy; - vec2 texCoords = vec2(pixelLocation)/vec2(imageSize(brdfLUT)); + vec2 texCoords = (vec2(pixelLocation)+vec2(0.5))/vec2(imageSize(brdfLUT)); vec2 integratedBRDF = IntegrateBRDF(texCoords.x, texCoords.y); imageStore(brdfLUT, ivec2(pixelLocation), vec4(integratedBRDF,0,0)); } \ No newline at end of file diff --git a/ArchitectureColoredPainting/res/Shaders/model.frag b/ArchitectureColoredPainting/res/Shaders/model.frag index dac9416..e2cd1ec 100644 --- a/ArchitectureColoredPainting/res/Shaders/model.frag +++ b/ArchitectureColoredPainting/res/Shaders/model.frag @@ -36,7 +36,6 @@ vec3 getNormalFromMap() void main() { - //gBaseColor = vec4(1,0,0,1); gBaseColor = texture(texture_basecolor, TexCoords); if(gBaseColor.a<0.4) discard; diff --git a/ArchitectureColoredPainting/res/Shaders/shader.frag b/ArchitectureColoredPainting/res/Shaders/shader.frag index 6062cfb..65f781b 100644 --- a/ArchitectureColoredPainting/res/Shaders/shader.frag +++ b/ArchitectureColoredPainting/res/Shaders/shader.frag @@ -1,133 +1,25 @@ -#version 330 core +#version 450 core - -uniform sampler2D texture_basecolor; -uniform sampler2D texture_metallic_roughness; -uniform sampler2D texture_normal; +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; +layout (location = 4) out uint gPaintingIndex; -out vec4 FragColor; in vec2 TexCoords; in vec3 WorldPos; in vec3 Normal; -// lights -uniform vec3 lightPositions[4]; -uniform vec3 lightColors[4]; +// material parameters +uniform vec3 albedo; +uniform float metallic; +uniform float roughness; -uniform vec3 camPos; - -const float PI = 3.14159265359; - -vec3 getNormalFromMap() -{ - vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0; - - vec3 Q1 = dFdx(WorldPos); - vec3 Q2 = dFdy(WorldPos); - vec2 st1 = dFdx(TexCoords); - vec2 st2 = dFdy(TexCoords); - - vec3 N = normalize(Normal); - vec3 T = normalize(Q1*st2.t - Q2*st1.t); - vec3 B = -normalize(cross(N, T)); - mat3 TBN = mat3(T, B, N); - - return normalize(TBN * tangentNormal); -} -// ---------------------------------------------------------------------------- -float DistributionGGX(vec3 N, vec3 H, float roughness) -{ - float a = roughness*roughness; - float a2 = a*a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH*NdotH; - - float nom = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; - - return nom / denom; -} -// ---------------------------------------------------------------------------- -float GeometrySchlickGGX(float NdotV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - - float nom = NdotV; - float denom = NdotV * (1.0 - k) + k; - - return nom / denom; -} -// ---------------------------------------------------------------------------- -float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) -{ - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); - - return ggx1 * ggx2; -} -// ---------------------------------------------------------------------------- -vec3 fresnelSchlick(float cosTheta, vec3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} void main() -{ - vec4 baseColor = texture(texture_basecolor, TexCoords); - if(baseColor.a<0.4) - discard; - - vec3 albedo = pow(baseColor.rgb, vec3(2.2)); - float metallic = texture(texture_metallic_roughness, TexCoords).b; - float roughness = texture(texture_metallic_roughness, TexCoords).g; - - - vec3 N = getNormalFromMap(); - vec3 V = normalize(camPos - WorldPos); - - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); - - // reflectance equation - vec3 Lo = vec3(0.0); - for(int i = 0; i < 1; ++i) - { - // calculate per-light radiance - vec3 L = normalize(lightPositions[i] - WorldPos); - vec3 H = normalize(V + L); - float distance = length(lightPositions[i] - WorldPos); - float attenuation = 1.0 / (distance * distance); - vec3 radiance = lightColors[i] * attenuation; - - // cook-torrance brdf - float NDF = DistributionGGX(N, H, roughness); - float G = GeometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), 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; - vec3 color = ambient + Lo; - - color = color / (color + vec3(1.0)); - color = pow(color, vec3(1.0/2.2)); - - FragColor = vec4(color, 1.0); - +{ + gBaseColor = vec4(albedo, 1); + gPosition = WorldPos; + gNormal = normalize(Normal); + gMetallicRoughness = vec2(metallic,roughness); + gPaintingIndex = 0; } \ No newline at end of file diff --git a/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp b/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp index a0a8cec..f65c5f6 100644 --- a/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp +++ b/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp @@ -75,26 +75,26 @@ vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); } -vec3 ambientLighting(vec3 N, vec3 V, vec3 F0, vec3 albedo,float metallic, float roughness, float ao) +vec3 ambientLighting(vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness, float ao) { // ambient lighting (we now use IBL as the ambient term) - vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness); + vec3 F = fresnelSchlickRoughness(clamp(dot(N, V),0.,1.), F0, roughness); vec3 kS = F; vec3 kD = 1.0 - kS; kD *= 1.0 - metallic; vec3 irradiance = texture(irradianceMap, N).rgb; - vec3 diffuse = irradiance * albedo; + vec3 diffuse = irradiance * albedo; // sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. const float MAX_REFLECTION_LOD = 4.0; vec3 R = reflect(-V, N); vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb; - vec2 brdf = texture(brdfLUT, vec2(max(dot(N, V), 0.0), roughness)).rg; + vec2 brdf = texture(brdfLUT, vec2(clamp(dot(N, V),0.,1.), roughness)).rg; vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); - return (kD * diffuse + specular) * ao; + return (kD * diffuse + specular) * ao; } @@ -200,7 +200,7 @@ void main() imageStore(gBaseColor, pixelLocation, vec4(0)); return; } - + normal = normalize(normal); vec3 V = normalize(camPos - worldPos); diff --git a/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp b/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp index b16c6f2..28cbd98 100644 --- a/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp +++ b/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #define STB_IMAGE_IMPLEMENTATION #include @@ -77,6 +78,101 @@ void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc) glFunc->glBindVertexArray(0); } +void Renderer::IblUtils::renderSphere(QOpenGLFunctions_4_5_Core* glFunc) +{ + static unsigned int sphereVAO = 0; + static unsigned int indexCount; + if (sphereVAO == 0) + { + glFunc->glGenVertexArrays(1, &sphereVAO); + + unsigned int vbo, ebo; + glFunc->glGenBuffers(1, &vbo); + glFunc->glGenBuffers(1, &ebo); + + std::vector positions; + std::vector uv; + std::vector normals; + std::vector indices; + + const unsigned int X_SEGMENTS = 64; + const unsigned int Y_SEGMENTS = 64; + const float PI = 3.14159265359f; + for (unsigned int x = 0; x <= X_SEGMENTS; ++x) + { + for (unsigned int y = 0; y <= Y_SEGMENTS; ++y) + { + float xSegment = (float)x / (float)X_SEGMENTS; + float ySegment = (float)y / (float)Y_SEGMENTS; + float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI); + float yPos = std::cos(ySegment * PI); + float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI); + + positions.push_back(glm::vec3(xPos, yPos, zPos)); + uv.push_back(glm::vec2(xSegment, ySegment)); + normals.push_back(glm::vec3(xPos, yPos, zPos)); + } + } + + bool oddRow = false; + for (unsigned int y = 0; y < Y_SEGMENTS; ++y) + { + if (!oddRow) // even rows: y == 0, y == 2; and so on + { + for (unsigned int x = 0; x <= X_SEGMENTS; ++x) + { + indices.push_back(y * (X_SEGMENTS + 1) + x); + indices.push_back((y + 1) * (X_SEGMENTS + 1) + x); + } + } + else + { + for (int x = X_SEGMENTS; x >= 0; --x) + { + indices.push_back((y + 1) * (X_SEGMENTS + 1) + x); + indices.push_back(y * (X_SEGMENTS + 1) + x); + } + } + oddRow = !oddRow; + } + indexCount = static_cast(indices.size()); + + std::vector data; + for (unsigned int i = 0; i < positions.size(); ++i) + { + data.push_back(positions[i].x); + data.push_back(positions[i].y); + data.push_back(positions[i].z); + if (normals.size() > 0) + { + data.push_back(normals[i].x); + data.push_back(normals[i].y); + data.push_back(normals[i].z); + } + if (uv.size() > 0) + { + data.push_back(uv[i].x); + data.push_back(uv[i].y); + } + } + glFunc->glBindVertexArray(sphereVAO); + glFunc->glBindBuffer(GL_ARRAY_BUFFER, vbo); + glFunc->glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW); + glFunc->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glFunc->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); + unsigned int stride = (3 + 2 + 3) * sizeof(float); + glFunc->glEnableVertexAttribArray(0); + glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); + glFunc->glEnableVertexAttribArray(1); + glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); + glFunc->glEnableVertexAttribArray(2); + glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6 * sizeof(float))); + } + + glFunc->glBindVertexArray(sphereVAO); + glFunc->glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); +} + std::tuple Renderer::IblUtils::precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc) { // pbr: setup framebuffer diff --git a/ArchitectureColoredPainting/src/Renderer/IblUtils.h b/ArchitectureColoredPainting/src/Renderer/IblUtils.h index fdfb56b..2305976 100644 --- a/ArchitectureColoredPainting/src/Renderer/IblUtils.h +++ b/ArchitectureColoredPainting/src/Renderer/IblUtils.h @@ -8,10 +8,13 @@ namespace Renderer public: static constexpr int cubemapSize = 1024; static void renderCube(QOpenGLFunctions_4_5_Core* glFunc); + static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc); /** * @brief * @return GLuint envCubemap * @return GLuint irradianceMap + * @return GLuint prefilterMap + * @return GLuint brdfLut */ static std::tuple precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc); private: diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp index 0507472..31310e9 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp @@ -121,6 +121,14 @@ void RendererGLWidget::initializeGL() if (!shadowProgramPtr->link()) qDebug() << "ERROR:" << shadowProgramPtr->log(); + plainProgramPtr = new QOpenGLShaderProgram; + if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert")) + qDebug() << "ERROR:" << plainProgramPtr->log(); + if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag")) + qDebug() << "ERROR:" << plainProgramPtr->log(); + if (!plainProgramPtr->link()) + qDebug() << "ERROR:" << plainProgramPtr->log(); + modelProgramPtr = new QOpenGLShaderProgram; if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert")) qDebug() << "ERROR:" << modelProgramPtr->log(); @@ -302,6 +310,31 @@ void RendererGLWidget::paintGL() paintingProgramPtr->release(); if (model != nullptr) model->draw(); + + plainProgramPtr->bind(); + plainProgramPtr->setUniformValue("projection", projection); + plainProgramPtr->setUniformValue("view", view); + plainProgramPtr->setUniformValue("albedo", 0.5f, 0.5f, 0.5f); + QMatrix4x4 model; + int nrRows = 7, nrColumns = 7; + float spacing = 2.5; + for (int row = 0; row < nrRows; ++row) + { + plainProgramPtr->setUniformValue("metallic", (float)row / (float)nrRows); + for (int col = 0; col < nrColumns; ++col) + { + plainProgramPtr->setUniformValue("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); + + model.setToIdentity(); + model.scale(10); + model.translate(QVector3D((float)(col - (nrColumns / 2)) * spacing, + (float)(row - (nrRows / 2)) * spacing+20, + -2.0f)); + plainProgramPtr->setUniformValue("model", model); + IblUtils::renderSphere(glFunc); + } + } + plainProgramPtr->release(); fboPtr->release(); } diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h index 6fa8d5e..23945f3 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h @@ -51,6 +51,7 @@ namespace Renderer float exposure = 0.8; QOpenGLShaderProgram* shadowProgramPtr = nullptr; + QOpenGLShaderProgram* plainProgramPtr = nullptr; QOpenGLShaderProgram* modelProgramPtr = nullptr; QOpenGLShaderProgram* paintingProgramPtr = nullptr; QOpenGLShaderProgram* paintingCompProgramPtr = nullptr;