diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index d4bc6d4..d89b5f2 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -99,6 +99,10 @@ + + + + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index b1417b5..8e6f9a5 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -68,6 +68,18 @@ Resource Files\Shaders + + Resource Files\Shaders + + + Resource Files\Shaders + + + Resource Files\Shaders + + + Resource Files\Shaders + diff --git a/ArchitectureColoredPainting/MainWindow.qrc b/ArchitectureColoredPainting/MainWindow.qrc index a7b91f5..abee18a 100644 --- a/ArchitectureColoredPainting/MainWindow.qrc +++ b/ArchitectureColoredPainting/MainWindow.qrc @@ -2,5 +2,10 @@ Shaders/shader.frag Shaders/shader.vert + Shaders/model.frag + Shaders/model.vert + Shaders/final.frag + Shaders/final.vert + container.jpg diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp index 669a5b3..c6b8aa2 100644 --- a/ArchitectureColoredPainting/RendererWidget.cpp +++ b/ArchitectureColoredPainting/RendererWidget.cpp @@ -15,12 +15,11 @@ RendererWidget::RendererWidget(QWidget* parent) RendererWidget::~RendererWidget() { - if (m_program == nullptr) + if (modelProgramPtr == nullptr) return; makeCurrent(); - m_vbo.destroy(); - delete m_program; - m_program = nullptr; + delete modelProgramPtr; + modelProgramPtr = nullptr; doneCurrent(); } @@ -32,33 +31,46 @@ void RendererWidget::initializeGL() glEnable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 1); - m_program = new QOpenGLShaderProgram; - if (!m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert")) - qDebug() << "ERROR:" << m_program->log(); - if (!m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag")) - qDebug() << "ERROR:" << m_program->log(); - if (!m_program->link()) - qDebug() << "ERROR:" << m_program->log(); - m_program->bind(); + modelProgramPtr = new QOpenGLShaderProgram; + if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert")) + qDebug() << "ERROR:" << modelProgramPtr->log(); + if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model.frag")) + qDebug() << "ERROR:" << modelProgramPtr->log(); + if (!modelProgramPtr->link()) + qDebug() << "ERROR:" << modelProgramPtr->log(); - model = Model::createModel("Models/Sponza/Sponza.gltf", context(), m_program); + finalProgramPtr = new QOpenGLShaderProgram; + if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert")) + qDebug() << "ERROR:" << finalProgramPtr->log(); + if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/final.frag")) + qDebug() << "ERROR:" << finalProgramPtr->log(); + if (!finalProgramPtr->link()) + qDebug() << "ERROR:" << finalProgramPtr->log(); + finalProgramPtr->bind(); + finalProgramPtr->setUniformValue("gBaseColor", 0); + finalProgramPtr->setUniformValue("gNormal", 1); + finalProgramPtr->setUniformValue("gPosition", 2); + finalProgramPtr->setUniformValue("gMetallicRoughness", 3); + finalProgramPtr->release(); - /*m_vao.create(); - QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); - - m_vbo.create(); - m_vbo.bind(); + model = Model::createModel("Models/Sponza/Sponza.gltf", context(), modelProgramPtr); + quadVAO.create(); + QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); + quadVBO.create(); + quadVBO.bind(); GLfloat vertex[] = { - -1,-1, 0, 0,0, - 1,-1, 0, 1,0, - -1, 1, 0, 0,1, + // positions // texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, }; - m_vbo.allocate(vertex, sizeof(vertex)); - m_vbo.bind(); + quadVBO.allocate(vertex, sizeof(vertex)); + quadVBO.bind(); QOpenGLFunctions_4_5_Compatibility* f = QOpenGLContext::currentContext()->versionFunctions(); f->glEnableVertexAttribArray(0); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), @@ -66,37 +78,70 @@ void RendererWidget::initializeGL() f->glEnableVertexAttribArray(1); f->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), reinterpret_cast(3 * sizeof(GLfloat))); - m_vbo.release();*/ + quadVBO.release(); + + + } QVector3D lightPositions[] = { QVector3D(0,0,0), QVector3D(100,100,100) ,QVector3D(-100,100,100) ,QVector3D(100,100,-100) }; -QVector3D lightColors[] = { QVector3D(150000,150000,150000), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) }; +QVector3D lightColors[] = { QVector3D(150000,150000,130000), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) }; void RendererWidget::paintGL() { - //std::cout << (double)CLOCKS_PER_SEC/(std::clock() -lastFrame) << std::endl; + fboPtr->bind(); + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + modelProgramPtr->bind(); + modelProgramPtr->setUniformValue("view", camera.GetViewMatrix()); + model->draw(); + modelProgramPtr->release(); + } + fboPtr->release(); + //QOpenGLFramebufferObject::blitFramebuffer(nullptr, QRect(0, 0, 2*width(), 2*height()), fboPtr, QRect(0, 0, 1156, 756)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); + finalProgramPtr->bind(); - QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); - m_program->bind(); - // camera/view transformation - QMatrix4x4 view = camera.GetViewMatrix(); - m_program->setUniformValue(m_program->uniformLocation("view"), view); - m_program->setUniformValue(m_program->uniformLocation("camPos"), camera.Position); + finalProgramPtr->setUniformValue(modelProgramPtr->uniformLocation("camPos"), camera.Position); lightPositions[0] = camera.Position; - m_program->setUniformValueArray("lightPositions", lightPositions, 4); - m_program->setUniformValueArray("lightColors", lightColors, 4); - //glDrawArrays(GL_TRIANGLES, 0, 3); - model->draw(); - m_program->release(); + finalProgramPtr->setUniformValueArray("lightPositions", lightPositions, 4); + finalProgramPtr->setUniformValueArray("lightColors", lightColors, 4); + + QVector gbuffers = fboPtr->textures(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, gbuffers[0]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, gbuffers[1]); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, gbuffers[2]); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, gbuffers[3]); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + finalProgramPtr->release(); } void RendererWidget::resizeGL(int width, int height) { - m_program->bind(); - QMatrix4x4 projection; - projection.perspective(camera.Zoom, (float)width / (float)height, 10.f, 10000.0f); - m_program->setUniformValue(m_program->uniformLocation("projection"), projection); - + //qDebug() << devicePixelRatio() << width << height; + //glViewport(0, 0, (GLint)devicePixelRatio()*width, (GLint)devicePixelRatio()*height); + if (fboPtr != nullptr) + delete fboPtr; + fboPtr = new QOpenGLFramebufferObject(devicePixelRatio() * width, devicePixelRatio() * height, QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D); + fboPtr->bind(); + fboPtr->addColorAttachment(devicePixelRatio() * width, devicePixelRatio() * height, GL_RGB16F); + fboPtr->addColorAttachment(devicePixelRatio() * width, devicePixelRatio() * height, GL_RGB16F); + fboPtr->addColorAttachment(devicePixelRatio() * width, devicePixelRatio() * height, GL_RG); + GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; + glDrawBuffers(4, attachments); + fboPtr->bind(); + { + modelProgramPtr->bind(); + QMatrix4x4 projection; + projection.perspective(camera.Zoom, (float)width / (float)height, 10.f, 10000.0f); + modelProgramPtr->setUniformValue("projection", projection); + modelProgramPtr->release(); + } + fboPtr->release(); } void RendererWidget::timerEvent(QTimerEvent* event) diff --git a/ArchitectureColoredPainting/RendererWidget.h b/ArchitectureColoredPainting/RendererWidget.h index 3b25b67..ea254c8 100644 --- a/ArchitectureColoredPainting/RendererWidget.h +++ b/ArchitectureColoredPainting/RendererWidget.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "Camera.h" #include "Model.h" @@ -30,9 +31,11 @@ private: Camera camera; clock_t lastFrame; float deltaTime; - QOpenGLShaderProgram* m_program = nullptr; - QOpenGLBuffer m_vbo; - QOpenGLVertexArrayObject m_vao; + QOpenGLShaderProgram* modelProgramPtr = nullptr; + QOpenGLShaderProgram* finalProgramPtr = nullptr; + QOpenGLFramebufferObject* fboPtr = nullptr; + QOpenGLBuffer quadVBO; + QOpenGLVertexArrayObject quadVAO; Model* model; }; diff --git a/ArchitectureColoredPainting/Shaders/final.frag b/ArchitectureColoredPainting/Shaders/final.frag new file mode 100644 index 0000000..869800b --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/final.frag @@ -0,0 +1,112 @@ +#version 330 core + +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D gBaseColor; +uniform sampler2D gNormal; +uniform sampler2D gPosition; +uniform sampler2D gMetallicRoughness; + +// lights +uniform vec3 lightPositions[4]; +uniform vec3 lightColors[4]; + +uniform vec3 camPos; + +const float PI = 3.14159265359; + +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() +{ + vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2)); + float metallic = texture(gMetallicRoughness, TexCoords).g; + float roughness = texture(gMetallicRoughness, TexCoords).r; + + + vec3 N = texture(gNormal, TexCoords).xyz; + vec3 WorldPos = texture(gPosition, TexCoords).xyz; + 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); + +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/final.vert b/ArchitectureColoredPainting/Shaders/final.vert new file mode 100644 index 0000000..9988a20 --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/final.vert @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main() +{ + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/model.frag b/ArchitectureColoredPainting/Shaders/model.frag new file mode 100644 index 0000000..594331a --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/model.frag @@ -0,0 +1,47 @@ +#version 330 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; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + + + +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); +} + +void main() +{ + //gBaseColor = vec4(1,0,0,1); + gBaseColor = texture(texture_basecolor, TexCoords); + if(gBaseColor.a<0.4) + discard; + gPosition = WorldPos; + gNormal = getNormalFromMap(); + gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).gb; + + +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/model.vert b/ArchitectureColoredPainting/Shaders/model.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/model.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/shader.frag b/ArchitectureColoredPainting/Shaders/shader.frag index 31971f1..6062cfb 100644 --- a/ArchitectureColoredPainting/Shaders/shader.frag +++ b/ArchitectureColoredPainting/Shaders/shader.frag @@ -77,7 +77,7 @@ vec3 fresnelSchlick(float cosTheta, vec3 F0) void main() { vec4 baseColor = texture(texture_basecolor, TexCoords); - if(baseColor.a==0) + if(baseColor.a<0.4) discard; vec3 albedo = pow(baseColor.rgb, vec3(2.2)); diff --git a/ArchitectureColoredPainting/container.jpg b/ArchitectureColoredPainting/container.jpg new file mode 100644 index 0000000..50aa4c9 Binary files /dev/null and b/ArchitectureColoredPainting/container.jpg differ diff --git a/README.md b/README.md index c28cd9c..53d85ce 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,8 @@ 采用pbr材质,现在有一个光源和摄像机绑定,足以分辨出不同材质的效果 -TODO:改用延迟渲染,并指定一块材质使用独立管线进行纹理采样 \ No newline at end of file +TODO: + +- [x] 改用延迟渲染 + +- [ ] 指定一块材质使用独立管线进行纹理采样 \ No newline at end of file