From fa112820cca7627ec35c29c386f7d5dacea27294 Mon Sep 17 00:00:00 2001 From: wuyize Date: Tue, 6 Sep 2022 16:37:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E7=94=A8=E8=AE=BA=E6=96=87=E7=9A=84?= =?UTF-8?q?=E5=88=86=E5=89=B2=E6=96=B9=E6=A1=88=EF=BC=8C=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E7=94=BB=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 2 + ...rchitectureColoredPainting.vcxproj.filters | 6 + ArchitectureColoredPainting/MainWindow.qrc | 3 +- ArchitectureColoredPainting/Model.cpp | 47 +- .../RendererWidget.cpp | 179 ++- ArchitectureColoredPainting/RendererWidget.h | 4 +- .../Shaders/depth_init.comp | 2 +- .../Shaders/final.frag | 118 +- .../Shaders/painting.comp | 1059 ++++++++++++----- .../Shaders/shadow_mapping.comp | 177 +++ ArchitectureColoredPainting/Shaders/ssgi.comp | 413 +++++++ ArchitectureColoredPainting/container.jpg | Bin 122294 -> 0 bytes 12 files changed, 1521 insertions(+), 489 deletions(-) create mode 100644 ArchitectureColoredPainting/Shaders/shadow_mapping.comp create mode 100644 ArchitectureColoredPainting/Shaders/ssgi.comp delete mode 100644 ArchitectureColoredPainting/container.jpg diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 5477d66..62c0450 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -117,6 +117,8 @@ + + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index 6d7562f..ed08f43 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -116,6 +116,12 @@ Resource Files\Shaders + + Resource Files\Shaders + + + Resource Files\Shaders + diff --git a/ArchitectureColoredPainting/MainWindow.qrc b/ArchitectureColoredPainting/MainWindow.qrc index 7519888..150f170 100644 --- a/ArchitectureColoredPainting/MainWindow.qrc +++ b/ArchitectureColoredPainting/MainWindow.qrc @@ -6,7 +6,6 @@ Shaders/model.vert Shaders/final.frag Shaders/final.vert - container.jpg Shaders/painting.frag Shaders/painting.vert Shaders/painting.comp @@ -15,5 +14,7 @@ Shaders/depth_mipmap.comp Shaders/depth_init.comp Shaders/model_shadow.geom + Shaders/shadow_mapping.comp + Shaders/ssgi.comp diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp index 4b0c48d..31149b6 100644 --- a/ArchitectureColoredPainting/Model.cpp +++ b/ArchitectureColoredPainting/Model.cpp @@ -191,10 +191,9 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod 7,0, 7,GLuint(30. / 360 * 65536 + 1 * 65536) /*右儿子用来表示旋转角度和zIndex*/, 8,0, 7,0, //elememt0 1,2, - 5 + 0/*contour索引*/,5 + 12/*style索引,在elementData中位置*/, 3,4, - 5 + 2,5 + 12, 5 + 1,5 + 12, + 3 + 20/*contour索引,由于contour不定长,这里需要给到contour在elementIndex中位置*/,3 + 14/*style索引,在elementData中位置*/, 3+24,3+14, //elememt1 - 1 + 0/*line索引,element中第几条*/,1 + 25 + 1 + 0/*line索引,element中第几条*/,1 + 27 }; std::vector bvhBounds = { @@ -204,49 +203,43 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod QVector4D(-0.8,-0.8,-0.2,-0.1), QVector4D(-0.7,0.2,-0.2,0.7), QVector4D(0.2,-0.8,0.8,-0.1), QVector4D(0.2,0.1,0.8,0.8), //elememt0 QVector4D(-1,-1,1,1), - QVector4D(-1,-0.5,1,1), QVector4D(-1,-1,1,0.5), - QVector4D(-1,-1,1,-0.5), QVector4D(-1,-0.5,1,0.5), - //elememt1 - QVector4D(-1,0,1,1), + QVector4D(-1,-1,-0.2,1), QVector4D(-0.2,-1,1,1), + //elememt1 + QVector4D(-1,0,1,1) }; std::vector elementOffset = { //element0 7, //elementBvhRoot - 5, //elementBvhLength + 3, //elementBvhLength 0, //pointsOffset 0, //linesOffset - 28, //contoursOffset //element1 - 12, //elementBvhRoot + 10, //elementBvhRoot 1, //elementBvhLength - 19, //pointsOffset - 40, //linesOffset - 44 //contoursOffset + 21, //pointsOffset + 28, //linesOffset }; std::vector elementIndex = { //element0 //lines, 全部当作三阶贝塞尔, 每条线四个点索引 - 4,2,2,0, - 0,0,1,1, - 1,1,4,4, - 1,1,5,5, - 4,4,5,5, - 1,1,3,3, - 3,3,5,5, - //contours, 每个轮廓三个线索引 - 0,1,2, - 2,3,4, - 3,5,6, - //element2 + 0,1,1,2, + 0,0,3,3, + 3,4,4,5, + 2,2,5,5, + 5,5,6,6, + //contours, 第一个元素为线数,后面为轮廓线索引 + 3, 1,2,4, + 3, 0,2,3, + //element1 //lines - 0,1,2 + 0,1,1,2 }; std::vector elementData = { //element0 //points - -1,0.5, -1,-0.5, 0,1, 0,-1, 1,0.5, 1,-0.5, + -0.2,1, -0.2,-0.2, 1,-0.2, -1,1, -1,-1, 1,-1, 1,1, //fillStyle //fill 0, diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp index 3d171f2..36b6d9e 100644 --- a/ArchitectureColoredPainting/RendererWidget.cpp +++ b/ArchitectureColoredPainting/RendererWidget.cpp @@ -13,9 +13,13 @@ RendererWidget::RendererWidget(QWidget* parent) , camera(QVector3D(0.0f, 100.0f, 0.0f)) , light(&camera) { - startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate()); + //startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate()); + startTimer(1); lastFrame = std::clock(); setFocusPolicy(Qt::StrongFocus); + QSurfaceFormat format; + format.setSwapInterval(0); + setFormat(format); } RendererWidget::~RendererWidget() @@ -97,6 +101,18 @@ void RendererWidget::initializeGL() if (!depthMipmapProgramPtr->link()) qDebug() << "ERROR:" << depthMipmapProgramPtr->log(); + shadowMappingProgramPtr = new QOpenGLShaderProgram; + if (!shadowMappingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/shadow_mapping.comp")) + qDebug() << "ERROR:" << shadowMappingProgramPtr->log(); + if (!shadowMappingProgramPtr->link()) + qDebug() << "ERROR:" << shadowMappingProgramPtr->log(); + + ssgiProgramPtr = new QOpenGLShaderProgram; + if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp")) + qDebug() << "ERROR:" << ssgiProgramPtr->log(); + if (!ssgiProgramPtr->link()) + qDebug() << "ERROR:" << ssgiProgramPtr->log(); + finalProgramPtr = new QOpenGLShaderProgram; if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert")) qDebug() << "ERROR:" << finalProgramPtr->log(); @@ -116,17 +132,34 @@ void RendererWidget::initializeGL() depthInitProgramPtr->bind(); - depthInitProgramPtr->setUniformValue("depthBuffer", 6); + depthInitProgramPtr->setUniformValue("depthBuffer", 0); depthInitProgramPtr->release(); + shadowMappingProgramPtr->bind(); + shadowMappingProgramPtr->setUniformValue("gBaseColor", 0); + shadowMappingProgramPtr->setUniformValue("gNormal", 1); + shadowMappingProgramPtr->setUniformValue("gPosition", 2); + shadowMappingProgramPtr->setUniformValue("gMetallicRoughness", 3); + shadowMappingProgramPtr->setUniformValue("gShadowMap", 4); + shadowMappingProgramPtr->release(); + + ssgiProgramPtr->bind(); + ssgiProgramPtr->setUniformValue("gBaseColor", 0); + ssgiProgramPtr->setUniformValue("gNormal", 1); + ssgiProgramPtr->setUniformValue("gPosition", 2); + ssgiProgramPtr->setUniformValue("gMetallicRoughness", 3); + ssgiProgramPtr->setUniformValue("gDepth", 4); + ssgiProgramPtr->setUniformValue("gDirectLight", 5); finalProgramPtr->bind(); finalProgramPtr->setUniformValue("gBaseColor", 0); - finalProgramPtr->setUniformValue("gNormal", 1); + finalProgramPtr->setUniformValue("gDirectLight", 1); + finalProgramPtr->setUniformValue("gIndirectLight", 2); + /*finalProgramPtr->setUniformValue("gNormal", 1); finalProgramPtr->setUniformValue("gPosition", 2); finalProgramPtr->setUniformValue("gMetallicRoughness", 3); finalProgramPtr->setUniformValue("gDepth", 4); - finalProgramPtr->setUniformValue("gShadowMap", 5); + finalProgramPtr->setUniformValue("gDirectLight", 5);*/ @@ -193,50 +226,33 @@ void RendererWidget::initializeGL() } -QVector3D lightPositions[] = { 2000 * QVector3D(0.2, 4, 1).normalized(), QVector3D(100,100,100) ,QVector3D(-100,100,100) ,QVector3D(100,100,-100) }; +//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) }; static float sunPitch = 90, sunYaw = 80; static int sunSpeed = 10; void RendererWidget::paintGL() { - QMatrix4x4 lightProjection; - lightProjection.ortho(-1200.0f, 1200.0f, -900.0f, 900.0f, -2000.f, 5000.0f); - light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw))); light.lightDirection.setY(sin(qDegreesToRadians(sunPitch))); light.lightDirection.setZ(cos(qDegreesToRadians(sunPitch)) * sin(qDegreesToRadians(sunYaw))); light.lightDirection.normalize(); - lightPositions[0].setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw))); - lightPositions[0].setY(sin(qDegreesToRadians(sunPitch))); - lightPositions[0].setZ(cos(qDegreesToRadians(sunPitch)) * sin(qDegreesToRadians(sunYaw))); - //lightPositions[0] *= 2000; - QMatrix4x4 lightView; - lightView.lookAt(lightPositions[0], QVector3D(0, 0, 0), QVector3D(0, 1, 0)); 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()); } - //glBufferSubData(GL_UNIFORM_BUFFER, 0 * 16 * sizeof(GLfloat), 16 * sizeof(GLfloat), (lightProjection * lightView).data()); glBindBuffer(GL_UNIFORM_BUFFER, 0); { glBindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle); glViewport(0, 0, shadowMapResolution, shadowMapResolution); glClear(GL_DEPTH_BUFFER_BIT); - /*shadowProgramPtr->bind(); - shadowProgramPtr->setUniformValue("projection", lightProjection); - shadowProgramPtr->setUniformValue("view", lightView); - shadowProgramPtr->setUniformValue("mainLightPositon", lightPositions[0]); - shadowProgramPtr->setUniformValue("mainLightColor", lightColors[0]); - shadowProgramPtr->release();*/ //glCullFace(GL_FRONT); model->drawShadow(); //glCullFace(GL_BACK); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); } QMatrix4x4 projection; @@ -257,24 +273,21 @@ void RendererWidget::paintGL() paintingProgramPtr->release(); model->draw(); - + fboPtr->release(); } paintingCompProgramPtr->bind(); - //glActiveTexture(GL_TEXTURE4); - //glBindTexture(GL_TEXTURE_2D, gbuffers[4]); glBindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); glBindImageTexture(1, gbuffers[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG8); glBindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI); glBindImageTexture(3, gbuffers[5], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F); glDispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); - //glDispatchCompute(1,1, 1); paintingCompProgramPtr->release(); depthInitProgramPtr->bind(); - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gbuffers[6]); glBindImageTexture(0, gbuffers[7], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); glDispatchCompute(ceil(depthWidth / 8.), ceil(depthHeight / 8.), 1); @@ -289,26 +302,38 @@ void RendererWidget::paintGL() glDispatchCompute(ceil(depthWidth / 2 / 8 / 8.), ceil(depthHeight / 2 / 8 / 8.), 1); depthMipmapProgramPtr->release(); - - - glViewport(0, 0, frameWidth, frameHeight); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); - finalProgramPtr->bind(); - - finalProgramPtr->setUniformValue("camPos", camera.Position); - //finalProgramPtr->setUniformValue("lightSpaceMatrix", lightProjection * lightView); - //lightPositions[0] = camera.Position; - //finalProgramPtr->setUniformValueArray("lightPositions", lightPositions, 4); - //finalProgramPtr->setUniformValueArray("lightColors", lightColors, 4); - finalProgramPtr->setUniformValue("view", view); - finalProgramPtr->setUniformValue("farPlane", camera.FarPlane); - finalProgramPtr->setUniformValueArray("shadowCascadePlaneDistances", light.shadowCascadeLevels.data(), light.shadowCascadeLevels.size(), 1); - finalProgramPtr->setUniformValueArray("shadowBiases", light.frustumSizes.data(), light.frustumSizes.size(), 1); + shadowMappingProgramPtr->bind(); + shadowMappingProgramPtr->setUniformValue("view", view); + shadowMappingProgramPtr->setUniformValue("farPlane", camera.FarPlane); + shadowMappingProgramPtr->setUniformValueArray("shadowCascadePlaneDistances", light.shadowCascadeLevels.data(), light.shadowCascadeLevels.size(), 1); + shadowMappingProgramPtr->setUniformValueArray("shadowBiases", light.frustumSizes.data(), light.frustumSizes.size(), 1); //qDebug() << light.frustumSizes; - finalProgramPtr->setUniformValue("shadowCascadeCount", (GLint)light.shadowCascadeLevels.size()); - finalProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); - finalProgramPtr->setUniformValue("mainLightRadiance", lightColors[0]); + shadowMappingProgramPtr->setUniformValue("shadowCascadeCount", (GLint)light.shadowCascadeLevels.size()); + 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_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]); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer); + 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->setUniformValue("camPos", camera.Position); + ssgiProgramPtr->setUniformValue("cameraMatrix", projection * view); + ssgiProgramPtr->setUniformValue("projectionMatrix", projection); + ssgiProgramPtr->setUniformValue("viewMatrix", view); + ssgiProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); + ssgiProgramPtr->setUniformValue("mainLightRadiance", lightColors[0]); + ssgiProgramPtr->setUniformValue("rdSeed", QVector4D(rand(), rand(), rand(), rand())); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gbuffers[0]); glActiveTexture(GL_TEXTURE1); @@ -320,7 +345,34 @@ void RendererWidget::paintGL() glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, gbuffers[7]); glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer); + 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(); + + glViewport(0, 0, frameWidth, frameHeight); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); + finalProgramPtr->bind(); + /*finalProgramPtr->setUniformValue("camPos", camera.Position); + finalProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); + finalProgramPtr->setUniformValue("mainLightRadiance", lightColors[0]);*/ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, gbuffers[0]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, gbuffers[8]); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, gbuffers[9]); + //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]); + //glActiveTexture(GL_TEXTURE4); + //glBindTexture(GL_TEXTURE_2D, gbuffers[7]); + //glActiveTexture(GL_TEXTURE5); + //glBindTexture(GL_TEXTURE_2D, gbuffers[8]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); finalProgramPtr->release(); } @@ -336,7 +388,7 @@ void RendererWidget::resizeGL(int width, int height) if (fboPtr != nullptr) { - glDeleteTextures(7, gbuffers + 1); + glDeleteTextures(9, gbuffers + 1); delete fboPtr; } @@ -346,7 +398,7 @@ void RendererWidget::resizeGL(int width, int height) //BaseColor gbuffers[0] = fboPtr->texture(); - glGenTextures(7, gbuffers + 1); + glGenTextures(9, gbuffers + 1); //Normal glBindTexture(GL_TEXTURE_2D, gbuffers[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL); @@ -387,13 +439,20 @@ void RendererWidget::resizeGL(int width, int height) glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f })); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gbuffers[6], 0); + GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 }; + glDrawBuffers(6, attachments); + //gbuffers = fboPtr->textures(); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + qDebug() << "Framebuffer not complete!"; + + //HiZ, not bind to fbo depthWidth = ceil(frameWidth / 64.) * 64; depthHeight = ceil(frameHeight / 64.) * 64; qDebug() << depthWidth << depthHeight; glBindTexture(GL_TEXTURE_2D, gbuffers[7]); for (int i = 0; i <= 6; i++) glTexImage2D(GL_TEXTURE_2D, i, GL_R32F, depthWidth / pow(2, i), depthHeight / pow(2, i), 0, GL_RED, GL_FLOAT, NULL); - //glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, depthWidth, depthHeight, 0, GL_RED, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 6); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); @@ -401,13 +460,17 @@ void RendererWidget::resizeGL(int width, int height) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f })); + //DirectLight + glBindTexture(GL_TEXTURE_2D, gbuffers[8]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, frameWidth, frameHeight, 0, GL_RGBA, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //InDirectLight + glBindTexture(GL_TEXTURE_2D, gbuffers[9]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, frameWidth, frameHeight, 0, GL_RGBA, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 }; - glDrawBuffers(6, attachments); - //gbuffers = fboPtr->textures(); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - qDebug() << "Framebuffer not complete!"; fboPtr->release(); } @@ -421,7 +484,7 @@ void RendererWidget::resizeGL(int width, int height) } //shadowMapResolution = 1.5 * std::max(frameWidth, frameHeight); - shadowMapResolution = 4096; + shadowMapResolution = 2048; glGenFramebuffers(1, &shadowFboHandle); { glBindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle); diff --git a/ArchitectureColoredPainting/RendererWidget.h b/ArchitectureColoredPainting/RendererWidget.h index 33d81f1..0ceeb9f 100644 --- a/ArchitectureColoredPainting/RendererWidget.h +++ b/ArchitectureColoredPainting/RendererWidget.h @@ -46,9 +46,11 @@ private: QOpenGLShaderProgram* paintingCompProgramPtr = nullptr; QOpenGLShaderProgram* depthInitProgramPtr = nullptr; QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr; + QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr; + QOpenGLShaderProgram* ssgiProgramPtr = nullptr; QOpenGLShaderProgram* finalProgramPtr = nullptr; QOpenGLFramebufferObject* fboPtr = nullptr; - GLuint gbuffers[8]; + GLuint gbuffers[10]; GLuint shadowFboHandle = 0; GLuint shadowGbuffer; GLuint lightSpaceMatricesUBO; diff --git a/ArchitectureColoredPainting/Shaders/depth_init.comp b/ArchitectureColoredPainting/Shaders/depth_init.comp index 4331570..3734a99 100644 --- a/ArchitectureColoredPainting/Shaders/depth_init.comp +++ b/ArchitectureColoredPainting/Shaders/depth_init.comp @@ -9,6 +9,6 @@ layout(r32f, binding = 0) uniform image2D gDepth; void main() { ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); - float depth = textureLod(depthBuffer, vec2(pixelLocation)/textureSize(depthBuffer, 0), 0).r; + float depth = textureLod(depthBuffer, vec2(pixelLocation+vec2(0.5))/textureSize(depthBuffer, 0), 0).r; imageStore(gDepth, pixelLocation, vec4(depth)); } \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/final.frag b/ArchitectureColoredPainting/Shaders/final.frag index c9393c8..d947ecf 100644 --- a/ArchitectureColoredPainting/Shaders/final.frag +++ b/ArchitectureColoredPainting/Shaders/final.frag @@ -9,22 +9,11 @@ uniform sampler2D gNormal; uniform sampler2D gPosition; uniform sampler2D gMetallicRoughness; uniform sampler2D gDepth; +uniform sampler2D gDirectLight; +uniform sampler2D gIndirectLight; -uniform sampler2DArray gShadowMap; -layout (std140, binding = 0) uniform LightSpaceMatrices -{ - mat4 lightSpaceMatrices[16]; -}; -uniform mat4 view; -uniform float farPlane; -uniform float shadowCascadePlaneDistances[16]; -uniform float shadowBiases[16]; -uniform int shadowCascadeCount; uniform vec3 mainLightDirection; uniform vec3 mainLightRadiance; -// lights -//uniform vec3 lightPositions[4]; -//uniform vec3 lightColors[4]; uniform vec3 camPos; @@ -70,87 +59,6 @@ vec3 fresnelSchlick(float cosTheta, vec3 F0) return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); } -float Calculate_Avg_Dblockreceiver(vec2 projCoords , int AvgTextureSize) -{ - vec2 texelSize =1.0/ textureSize(gShadowMap, 0).xy; - float result=0.0f; - for(int i=-AvgTextureSize;i<=AvgTextureSize;++i) - { - for(int j=-AvgTextureSize;j<=AvgTextureSize;j++) - { - result += texture(gShadowMap, vec3( projCoords+vec2(i,j)*texelSize, 0)).r; - } - } - return result/(AvgTextureSize*AvgTextureSize*2*2); -} - -float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer) -{ - // select cascade layer - vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0); - float depthValue = abs(fragPosViewSpace.z); - - layer = -1; - for (int i = 0; i < shadowCascadeCount; ++i) - { - if (depthValue < shadowCascadePlaneDistances[i]) - { - layer = i; - break; - } - } - if (layer == -1) - { - layer = shadowCascadeCount; - } - - int pcfRadius = 3; - float normalBias = 4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x; - vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0); - // perform perspective divide - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - // transform to [0,1] range - projCoords = projCoords * 0.5 + 0.5; - - // get depth of current fragment from light's perspective - float currentDepth = projCoords.z; - - // keep the shadow at 0.0 when outside the far_plane region of the light's frustum. - if (currentDepth > 1.0) - { - return 0.0; - } - // calculate bias (based on depth map resolution and slope) - - //float bias = 1* max(0.05 * (1.0 - dot(normal, mainLightDirection)), 0.005); - //const float biasModifier = 0.5f; -// if (layer == shadowCascadeCount) -// { -// bias *= 1 / (farPlane * biasModifier); -// } -// else -// { -// bias *= 1 / (shadowCascadePlaneDistances[layer] * biasModifier); -// } - - // PCF - float shadow = 0.0; - vec2 texelSize = 1.0 / vec2(textureSize(gShadowMap, 0)); - for(int x = -pcfRadius; x <= pcfRadius; ++x) - { - for(int y = -pcfRadius; y <= pcfRadius; ++y) - { - float pcfDepth = texture(gShadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r; - //shadow += (currentDepth - bias) > pcfDepth ? 1.0 : 0.0; - shadow += currentDepth > pcfDepth ? 1.0 : 0.0; - } - } - shadow /= (2*pcfRadius+1)*(2*pcfRadius+1); - - return shadow; -} - - void main() { @@ -161,19 +69,24 @@ void main() //depth -= texelFetch(gDepth, depthCoords, 0).x; //FragColor = vec4(vec3(depth*10000),1); //FragColor = vec4(vec3(textureSize(gShadowMap, 0)-vec3(1)),1); - //FragColor = vec4(texture(gBaseColor, TexCoords).rgb, 1); - //return; + //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; + color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + FragColor = vec4(color, 1.0); + return; - vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2)); + float metallic = texture(gMetallicRoughness, TexCoords).r; float roughness = texture(gMetallicRoughness, TexCoords).g; - vec3 N = normalize(texture(gNormal, TexCoords).xyz); + vec3 N = texture(gNormal, TexCoords).xyz; vec3 WorldPos = texture(gPosition, TexCoords).xyz; - if(WorldPos==vec3(0)) + if(N==vec3(0)) { vec3 color = mainLightRadiance; @@ -225,12 +138,13 @@ void main() //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); + //int debugLayer; + //float shadow = ShadowCalculation(WorldPos, N, debugLayer); //vec3 color = ambient + Lo; //vec3 color = indirect*1; - vec3 color = ambient + (1.0 - shadow) * Lo; + 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; diff --git a/ArchitectureColoredPainting/Shaders/painting.comp b/ArchitectureColoredPainting/Shaders/painting.comp index 50dc9c6..83b23b8 100644 --- a/ArchitectureColoredPainting/Shaders/painting.comp +++ b/ArchitectureColoredPainting/Shaders/painting.comp @@ -18,30 +18,29 @@ layout(std430, binding = 1) buffer paintingOffsetBuffer layout(std430, binding = 2) buffer bvhBuffer { - uvec2 bvhChildren[]; + uvec2 bvhChildren[]; }; layout(std430, binding = 3) buffer bvhBoundBuffer { - vec4 bvhBound[]; + vec4 bvhBound[]; }; layout(std430, binding = 4) buffer elementOffsetBuffer { - /********************** - ** @[0] elementBvhRoot - ** @[1] elementBvhLength - ** @[2] pointsOffset - ** @[3] linesOffset - ** @[4] contoursOffset - **********************/ - uint elementOffset[][5]; + /********************** + ** @[0] elementBvhRoot + ** @[1] elementBvhLength + ** @[2] pointsOffset + ** @[3] linesOffset + **********************/ + uint elementOffset[][4]; }; layout(std430, binding = 5) buffer elementIndexBuffer { - uint elementIndexs[]; //线和面 + uint elementIndexs[]; //线和面 }; layout(std430, binding = 6) buffer elementDataBuffer { - float elementData[]; //点和Style + float elementData[]; //点和Style }; const float PI = 3.14159265358979; @@ -50,39 +49,39 @@ const uint STACK_SIZE = 16; struct Stack { - uint top; - uint data[STACK_SIZE]; + uint top; + uint data[STACK_SIZE]; - bool empty() - { - return top == 0; - } - bool full() - { - return top == STACK_SIZE; - } - bool getTop(out uint x) - { - if (empty()) - return false; - x = data[top - 1]; - return true; - } - bool pop() - { - if (empty()) - return false; - top--; - return true; - } - bool push(in uint x) - { - if (full()) - return false; - data[top] = x; - top++; - return true; - } + bool empty() + { + return top == 0; + } + bool full() + { + return top == STACK_SIZE; + } + bool getTop(out uint x) + { + if (empty()) + return false; + x = data[top - 1]; + return true; + } + bool pop() + { + if (empty()) + return false; + top--; + return true; + } + bool push(in uint x) + { + if (full()) + return false; + data[top] = x; + top++; + return true; + } } stack, elementStack; @@ -91,23 +90,23 @@ struct Stack int solve_quadric(vec2 coeffs, inout vec2 roots) { - // normal form: x^2 + px + q = 0 - float p = coeffs[1] / 2.; - float q = coeffs[0]; + // normal form: x^2 + px + q = 0 + float p = coeffs[1] / 2.; + float q = coeffs[0]; - float D = p * p - q; + float D = p * p - q; - if (D < 0.) - { - return 0; - } - else - { - roots[0] = -sqrt(D) - p; - roots[1] = sqrt(D) - p; + if (D < 0.) + { + return 0; + } + else + { + roots[0] = -sqrt(D) - p; + roots[1] = sqrt(D) - p; - return 2; - } + return 2; + } } // From Trisomie21 @@ -115,308 +114,770 @@ int solve_quadric(vec2 coeffs, inout vec2 roots) int solve_cubic(vec3 coeffs, inout vec3 r) { - float a = coeffs[2]; - float b = coeffs[1]; - float c = coeffs[0]; + float a = coeffs[2]; + float b = coeffs[1]; + float c = coeffs[0]; - float p = b - a * a / 3.0; - float q = a * (2.0 * a * a - 9.0 * b) / 27.0 + c; - float p3 = p * p * p; - float d = q * q + 4.0 * p3 / 27.0; - float offset = -a / 3.0; - if (d >= 0.0) - { // Single solution - float z = sqrt(d); - float u = (-q + z) / 2.0; - float v = (-q - z) / 2.0; - u = sign(u) * pow(abs(u), 1.0 / 3.0); - v = sign(v) * pow(abs(v), 1.0 / 3.0); - r[0] = offset + u + v; + float p = b - a * a / 3.0; + float q = a * (2.0 * a * a - 9.0 * b) / 27.0 + c; + float p3 = p * p * p; + float d = q * q + 4.0 * p3 / 27.0; + float offset = -a / 3.0; + if (d >= 0.0) + { // Single solution + float z = sqrt(d); + float u = (-q + z) / 2.0; + float v = (-q - z) / 2.0; + u = sign(u) * pow(abs(u), 1.0 / 3.0); + v = sign(v) * pow(abs(v), 1.0 / 3.0); + r[0] = offset + u + v; - // Single newton iteration to account for cancellation - float f = ((r[0] + a) * r[0] + b) * r[0] + c; - float f1 = (3. * r[0] + 2. * a) * r[0] + b; + // Single newton iteration to account for cancellation + float f = ((r[0] + a) * r[0] + b) * r[0] + c; + float f1 = (3. * r[0] + 2. * a) * r[0] + b; - r[0] -= f / f1; + r[0] -= f / f1; - return 1; - } - float u = sqrt(-p / 3.0); - float v = acos(-sqrt(-27.0 / p3) * q / 2.0) / 3.0; - float m = cos(v), n = sin(v) * 1.732050808; + return 1; + } + float u = sqrt(-p / 3.0); + float v = acos(-sqrt(-27.0 / p3) * q / 2.0) / 3.0; + float m = cos(v), n = sin(v) * 1.732050808; - // Single newton iteration to account for cancellation - //(once for every root) - r[0] = offset + u * (m + m); - r[1] = offset - u * (n + m); - r[2] = offset + u * (n - m); + // Single newton iteration to account for cancellation + //(once for every root) + r[0] = offset + u * (m + m); + r[1] = offset - u * (n + m); + r[2] = offset + u * (n - m); - vec3 f = ((r + a) * r + b) * r + c; - vec3 f1 = (3. * r + 2. * a) * r + b; + vec3 f = ((r + a) * r + b) * r + c; + vec3 f1 = (3. * r + 2. * a) * r + b; - r -= f / f1; + r -= f / f1; - return 3; + return 3; } int segment_int_test(vec2 uv, vec2 p0, vec2 p1) { - p0 -= uv; - p1 -= uv; + p0 -= uv; + p1 -= uv; - int ret; + int ret; - if (p0.y * p1.y < 0.) - { - vec2 nor = p0 - p1; - nor = vec2(nor.y, -nor.x); + if (p0.y * p1.y < 0.) + { + vec2 nor = p0 - p1; + nor = vec2(nor.y, -nor.x); - float sgn; + float sgn; - if (p0.y > p1.y) - { - sgn = 1.; - } - else - { - sgn = -1.; - } + if (p0.y > p1.y) + { + sgn = 1.; + } + else + { + sgn = -1.; + } - if (dot(nor, p0) * sgn < 0.) - { - ret = 0; - } - else - { - ret = 1; - } - } - else - { - ret = 0; - } + if (dot(nor, p0) * sgn < 0.) + { + ret = 0; + } + else + { + ret = 1; + } + } + else + { + ret = 0; + } - return ret; + return ret; } int cubic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3) { - float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y); - float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y); - float li = (-3. * p0.y + 3. * p1.y); - float co = p0.y - uv.y; + float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y); + float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y); + float li = (-3. * p0.y + 3. * p1.y); + float co = p0.y - uv.y; - vec3 roots = vec3(1e38); - int n_roots; + vec3 roots = vec3(1e38); + int n_roots; - int n_ints = 0; + int n_ints = 0; - if (uv.x < min(min(p0.x, p1.x), min(p2.x, p3.x))) - { - if (uv.y >= min(p0.y, p3.y) && uv.y <= max(p0.y, p3.y)) - { - n_ints = 1; - } - } - else + if (uv.x < min(min(p0.x, p1.x), min(p2.x, p3.x))) + { + if (uv.y >= min(p0.y, p3.y) && uv.y <= max(p0.y, p3.y)) + { + n_ints = 1; + } + } + else + { + + if (abs(cu) < .0001) + { + n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy); + } + else + { + n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots); + } + + for (int i = 0; i < n_roots; i++) + { + if (roots[i] >= 0. && roots[i] <= 1.) + { + float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x; + x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x; + x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x; + x_pos = x_pos * roots[i] + p0.x; + + if (x_pos > uv.x) + { + n_ints++; + } + } + } + } + + return n_ints; +} + +const float eps = .000005; +const int halley_iterations = 8; +//lagrange positive real root upper bound +//see for example: https://doi.org/10.1016/j.jsc.2014.09.038 +float upper_bound_lagrange5(float a0, float a1, float a2, float a3, float a4){ + + vec4 coeffs1 = vec4(a0,a1,a2,a3); + + vec4 neg1 = max(-coeffs1,vec4(0)); + float neg2 = max(-a4,0.); + + const vec4 indizes1 = vec4(0,1,2,3); + const float indizes2 = 4.; + + vec4 bounds1 = pow(neg1,1./(5.-indizes1)); + float bounds2 = pow(neg2,1./(5.-indizes2)); + + vec2 min1_2 = min(bounds1.xz,bounds1.yw); + vec2 max1_2 = max(bounds1.xz,bounds1.yw); + + float maxmin = max(min1_2.x,min1_2.y); + float minmax = min(max1_2.x,max1_2.y); + + float max3 = max(max1_2.x,max1_2.y); + + float max_max = max(max3,bounds2); + float max_max2 = max(min(max3,bounds2),max(minmax,maxmin)); + + return max_max + max_max2; +} + +//lagrange upper bound applied to f(-x) to get lower bound +float lower_bound_lagrange5(float a0, float a1, float a2, float a3, float a4){ + + vec4 coeffs1 = vec4(-a0,a1,-a2,a3); + + vec4 neg1 = max(-coeffs1,vec4(0)); + float neg2 = max(-a4,0.); + + const vec4 indizes1 = vec4(0,1,2,3); + const float indizes2 = 4.; + + vec4 bounds1 = pow(neg1,1./(5.-indizes1)); + float bounds2 = pow(neg2,1./(5.-indizes2)); + + vec2 min1_2 = min(bounds1.xz,bounds1.yw); + vec2 max1_2 = max(bounds1.xz,bounds1.yw); + + float maxmin = max(min1_2.x,min1_2.y); + float minmax = min(max1_2.x,max1_2.y); + + float max3 = max(max1_2.x,max1_2.y); + + float max_max = max(max3,bounds2); + float max_max2 = max(min(max3,bounds2),max(minmax,maxmin)); + + return -max_max - max_max2; +} + +vec2 parametric_cub_bezier(float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3){ + vec2 a0 = (-p0 + 3. * p1 - 3. * p2 + p3); + vec2 a1 = (3. * p0 -6. * p1 + 3. * p2); + vec2 a2 = (-3. * p0 + 3. * p1); + vec2 a3 = p0; + + return (((a0 * t) + a1) * t + a2) * t + a3; +} + +void sort_roots3(inout vec3 roots){ + vec3 tmp; + + tmp[0] = min(roots[0],min(roots[1],roots[2])); + tmp[1] = max(roots[0],min(roots[1],roots[2])); + tmp[2] = max(roots[0],max(roots[1],roots[2])); + + roots=tmp; +} + +void sort_roots4(inout vec4 roots){ + vec4 tmp; + + vec2 min1_2 = min(roots.xz,roots.yw); + vec2 max1_2 = max(roots.xz,roots.yw); + + float maxmin = max(min1_2.x,min1_2.y); + float minmax = min(max1_2.x,max1_2.y); + + tmp[0] = min(min1_2.x,min1_2.y); + tmp[1] = min(maxmin,minmax); + tmp[2] = max(minmax,maxmin); + tmp[3] = max(max1_2.x,max1_2.y); + + roots = tmp; +} + +float eval_poly5(float a0, float a1, float a2, float a3, float a4, float x){ + + float f = ((((x + a4) * x + a3) * x + a2) * x + a1) * x + a0; + + return f; +} + +//halley's method +//basically a variant of newton raphson which converges quicker and has bigger basins of convergence +//see http://mathworld.wolfram.com/HalleysMethod.html +//or https://en.wikipedia.org/wiki/Halley%27s_method +float halley_iteration5(float a0, float a1, float a2, float a3, float a4, float x){ + + float f = ((((x + a4) * x + a3) * x + a2) * x + a1) * x + a0; + float f1 = (((5. * x + 4. * a4) * x + 3. * a3) * x + 2. * a2) * x + a1; + float f2 = ((20. * x + 12. * a4) * x + 6. * a3) * x + 2. * a2; + + return x - (2. * f * f1) / (2. * f1 * f1 - f * f2); +} + +float halley_iteration4(vec4 coeffs, float x){ + + float f = (((x + coeffs[3]) * x + coeffs[2]) * x + coeffs[1]) * x + coeffs[0]; + float f1 = ((4. * x + 3. * coeffs[3]) * x + 2. * coeffs[2]) * x + coeffs[1]; + float f2 = (12. * x + 6. * coeffs[3]) * x + 2. * coeffs[2]; + + return x - (2. * f * f1) / (2. * f1 * f1 - f * f2); +} + +// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c +// Credits to Doublefresh for hinting there +int solve_quartic(vec4 coeffs, inout vec4 s){ + + float a = coeffs[3]; + float b = coeffs[2]; + float c = coeffs[1]; + float d = coeffs[0]; + + /* substitute x = y - A/4 to eliminate cubic term: + x^4 + px^2 + qx + r = 0 */ + + float sq_a = a * a; + float p = - 3./8. * sq_a + b; + float q = 1./8. * sq_a * a - 1./2. * a * b + c; + float r = - 3./256.*sq_a*sq_a + 1./16.*sq_a*b - 1./4.*a*c + d; + + int num; + + /* doesn't seem to happen for me */ + //if(abs(r)= 0. && roots[i] <= 1.) - { - float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x; - x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x; - x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x; - x_pos = x_pos * roots[i] + p0.x; + cubic_coeffs[0] = 1.0/2. * r * p - 1.0/8. * q * q; + cubic_coeffs[1] = - r; + cubic_coeffs[2] = - 1.0/2. * p; - if (x_pos > uv.x) - { - n_ints++; - } + solve_cubic(cubic_coeffs, s.xyz); + + /* ... and take the one real solution ... */ + + float z = s[0]; + + /* ... to build two quadric equations */ + + float u = z * z - r; + float v = 2. * z - p; + + if(u > -eps){ + u = sqrt(abs(u)); + } + else{ + return 0; + } + + if(v > -eps){ + v = sqrt(abs(v)); + } + else{ + return 0; + } + + vec2 quad_coeffs; + + quad_coeffs[0] = z - u; + quad_coeffs[1] = q < 0. ? -v : v; + + num = solve_quadric(quad_coeffs, s.xy); + + quad_coeffs[0]= z + u; + quad_coeffs[1] = q < 0. ? v : -v; + + vec2 tmp=vec2(1e38); + int old_num=num; + + num += solve_quadric(quad_coeffs, tmp); + if(old_num!=num){ + if(old_num == 0){ + s[0] = tmp[0]; + s[1] = tmp[1]; + } + else{//old_num == 2 + s[2] = tmp[0]; + s[3] = tmp[1]; } } } - return n_ints; -} + /* resubstitute */ + float sub = 1./4. * a; + + /* single halley iteration to fix cancellation */ + for(int i=0;i<4;i+=2){ + if(i < num){ + s[i] -= sub; + s[i] = halley_iteration4(coeffs,s[i]); + + s[i+1] -= sub; + s[i+1] = halley_iteration4(coeffs,s[i+1]); + } + } + + return num; +} +float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3){ + + //switch points when near to end point to minimize numerical error + //only needed when control point(s) very far away + #if 0 + vec2 mid_curve = parametric_cub_bezier(.5,p0,p1,p2,p3); + vec2 mid_points = (p0 + p3)/2.; + + vec2 tang = mid_curve-mid_points; + vec2 nor = vec2(tang.y,-tang.x); + + if(sign(dot(nor,uv-mid_curve)) != sign(dot(nor,p0-mid_curve))){ + vec2 tmp = p0; + p0 = p3; + p3 = tmp; + + tmp = p2; + p2 = p1; + p1 = tmp; + } + #endif + + vec2 a3 = (-p0 + 3. * p1 - 3. * p2 + p3); + vec2 a2 = (3. * p0 - 6. * p1 + 3. * p2); + vec2 a1 = (-3. * p0 + 3. * p1); + vec2 a0 = p0 - uv; + + //compute polynomial describing distance to current pixel dependent on a parameter t + float bc6 = dot(a3,a3); + float bc5 = 2.*dot(a3,a2); + float bc4 = dot(a2,a2) + 2.*dot(a1,a3); + float bc3 = 2.*(dot(a1,a2) + dot(a0,a3)); + float bc2 = dot(a1,a1) + 2.*dot(a0,a2); + float bc1 = 2.*dot(a0,a1); + float bc0 = dot(a0,a0); + + bc5 /= bc6; + bc4 /= bc6; + bc3 /= bc6; + bc2 /= bc6; + bc1 /= bc6; + bc0 /= bc6; + + //compute derivatives of this polynomial + + float b0 = bc1 / 6.; + float b1 = 2. * bc2 / 6.; + float b2 = 3. * bc3 / 6.; + float b3 = 4. * bc4 / 6.; + float b4 = 5. * bc5 / 6.; + + vec4 c1 = vec4(b1,2.*b2,3.*b3,4.*b4)/5.; + vec3 c2 = vec3(c1[1],2.*c1[2],3.*c1[3])/4.; + vec2 c3 = vec2(c2[1],2.*c2[2])/3.; + float c4 = c3[1]/2.; + + vec4 roots_drv = vec4(1e38); + + int num_roots_drv = solve_quartic(c1,roots_drv); + sort_roots4(roots_drv); + + float ub = upper_bound_lagrange5(b0,b1,b2,b3,b4); + float lb = lower_bound_lagrange5(b0,b1,b2,b3,b4); + + vec3 a = vec3(1e38); + vec3 b = vec3(1e38); + + vec3 roots = vec3(1e38); + + int num_roots = 0; + + //compute root isolating intervals by roots of derivative and outer root bounds + //only roots going form - to + considered, because only those result in a minimum + if(num_roots_drv==4){ + if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[0]) > 0.){ + a[0]=lb; + b[0]=roots_drv[0]; + num_roots=1; + } + + if(sign(eval_poly5(b0,b1,b2,b3,b4,roots_drv[1])) != sign(eval_poly5(b0,b1,b2,b3,b4,roots_drv[2]))){ + if(num_roots == 0){ + a[0]=roots_drv[1]; + b[0]=roots_drv[2]; + num_roots=1; + } + else{ + a[1]=roots_drv[1]; + b[1]=roots_drv[2]; + num_roots=2; + } + } + + if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[3]) < 0.){ + if(num_roots == 0){ + a[0]=roots_drv[3]; + b[0]=ub; + num_roots=1; + } + else if(num_roots == 1){ + a[1]=roots_drv[3]; + b[1]=ub; + num_roots=2; + } + else{ + a[2]=roots_drv[3]; + b[2]=ub; + num_roots=3; + } + } + } + else{ + if(num_roots_drv==2){ + if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[0]) < 0.){ + num_roots=1; + a[0]=roots_drv[1]; + b[0]=ub; + } + else if(eval_poly5(b0,b1,b2,b3,b4,roots_drv[1]) > 0.){ + num_roots=1; + a[0]=lb; + b[0]=roots_drv[0]; + } + else{ + num_roots=2; + + a[0]=lb; + b[0]=roots_drv[0]; + + a[1]=roots_drv[1]; + b[1]=ub; + } + + } + else{//num_roots_drv==0 + vec3 roots_snd_drv=vec3(1e38); + int num_roots_snd_drv=solve_cubic(c2,roots_snd_drv); + + vec2 roots_trd_drv=vec2(1e38); + int num_roots_trd_drv=solve_quadric(c3,roots_trd_drv); + num_roots=1; + + a[0]=lb; + b[0]=ub; + } + + //further subdivide intervals to guarantee convergence of halley's method + //by using roots of further derivatives + vec3 roots_snd_drv=vec3(1e38); + int num_roots_snd_drv=solve_cubic(c2,roots_snd_drv); + sort_roots3(roots_snd_drv); + + int num_roots_trd_drv=0; + vec2 roots_trd_drv=vec2(1e38); + + if(num_roots_snd_drv!=3){ + num_roots_trd_drv=solve_quadric(c3,roots_trd_drv); + } + + for(int i=0;i<3;i++){ + if(i < num_roots){ + for(int j=0;j<3;j+=2){ + if(j < num_roots_snd_drv){ + if(a[i] < roots_snd_drv[j] && b[i] > roots_snd_drv[j]){ + if(eval_poly5(b0,b1,b2,b3,b4,roots_snd_drv[j]) > 0.){ + b[i]=roots_snd_drv[j]; + } + else{ + a[i]=roots_snd_drv[j]; + } + } + } + } + for(int j=0;j<2;j++){ + if(j < num_roots_trd_drv){ + if(a[i] < roots_trd_drv[j] && b[i] > roots_trd_drv[j]){ + if(eval_poly5(b0,b1,b2,b3,b4,roots_trd_drv[j]) > 0.){ + b[i]=roots_trd_drv[j]; + } + else{ + a[i]=roots_trd_drv[j]; + } + } + } + } + } + } + } + + float d0 = 1e38; + + //compute roots with halley's method + + for(int i=0;i<3;i++){ + if(i < num_roots){ + roots[i] = .5 * (a[i] + b[i]); + + for(int j=0;j= elementBvhLength) - { - debugBVH.g += 0.5; + if (all(lessThan(bound.xy, localUV)) && all(lessThan(localUV, bound.zw))) + { + if (leftChild >= elementBvhLength) + { + debugBVH.g += 0.5; - uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y - elementBvhLength; - // for(int i = 0; i<200;i++) - if (elementData[styleIndex] == 0.) //面 - { - uint contourIndex = leftChild - elementBvhLength; - - uint num_its = 0; + uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y - elementBvhLength; + // for(int i = 0; i<200;i++) + if (elementData[styleIndex] == 0.) //面 + { + uint contourIndex = leftChild - elementBvhLength; + + uint num_its = 0; - uint contourIterator = contoursOffset + contourIndex*3; - if(elementIndexs[contourIterator]==elementIndexs[contourIterator+1]) - contourIterator++; - for (;contourIterator < contoursOffset + contourIndex*3 + 3; contourIterator++) - { - uint lineIndex = elementIndexs[contourIterator]; - uint p0Index = elementIndexs[linesOffset + 4 * lineIndex]; - uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1]; - uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2]; - uint p3Index = elementIndexs[linesOffset + 4 * lineIndex + 3]; + uint lineCount = elementIndexs[contourIndex]; + + for ( uint contourIterator = contourIndex + 1;contourIterator < contourIndex + 1 + lineCount; contourIterator++) + { + uint lineIndex = elementIndexs[contourIterator]; + uint p0Index = elementIndexs[linesOffset + 4 * lineIndex]; + uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1]; + uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2]; + uint p3Index = elementIndexs[linesOffset + 4 * lineIndex + 3]; - vec2 p0 = vec2(elementData[pointsOffset + 2 * p0Index], - elementData[pointsOffset + 2 * p0Index + 1]); - vec2 p1 = vec2(elementData[pointsOffset + 2 * p1Index], - elementData[pointsOffset + 2 * p1Index + 1]); - vec2 p2 = vec2(elementData[pointsOffset + 2 * p2Index], - elementData[pointsOffset + 2 * p2Index + 1]); - vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index], - elementData[pointsOffset + 2 * p3Index + 1]); + vec2 p0 = vec2(elementData[pointsOffset + 2 * p0Index], + elementData[pointsOffset + 2 * p0Index + 1]); + vec2 p1 = vec2(elementData[pointsOffset + 2 * p1Index], + elementData[pointsOffset + 2 * p1Index + 1]); + vec2 p2 = vec2(elementData[pointsOffset + 2 * p2Index], + elementData[pointsOffset + 2 * p2Index + 1]); + vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index], + elementData[pointsOffset + 2 * p3Index + 1]); - if (p0 == p1 && p2 == p3) - { - num_its += segment_int_test(localUV, p0, p3); - } + if (p0 == p1 && p2 == p3) + { + num_its += segment_int_test(localUV, p0, p3); + } - else - num_its += cubic_bezier_int_test(localUV, p0, p1, p2, p3); - } + else + num_its += cubic_bezier_int_test(localUV, p0, p1, p2, p3); + } - if (num_its % 2 == 1) - { - elementColor = vec4(1); - //debugHit = true; - } - } - else if (elementData[styleIndex] == 1) //线 - { - } + if (num_its % 2 == 1) + { + elementColor = vec4(1); + //debugHit = true; + } + } + else if (elementData[styleIndex] == 1) //线 + { + float strokeWidth = elementData[styleIndex+1]; + uint lineIndex = leftChild - elementBvhLength; + uint p0Index = elementIndexs[linesOffset + 4 * lineIndex]; + uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1]; + uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2]; + uint p3Index = elementIndexs[linesOffset + 4 * lineIndex + 3]; - elementBvhIndex = elementBvhLength; - } - else - { - // debugBVH.b += 0.2; - elementStack.push(elementBvhIndex); - elementBvhIndex = leftChild; - } - } - else - elementBvhIndex = elementBvhLength; - } - if (!elementStack.empty()) - { - elementStack.getTop(elementBvhIndex); - elementStack.pop(); - elementBvhIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y; - } - } - return elementColor.xyz; + vec2 p0 = vec2(elementData[pointsOffset + 2 * p0Index], + elementData[pointsOffset + 2 * p0Index + 1]); + vec2 p1 = vec2(elementData[pointsOffset + 2 * p1Index], + elementData[pointsOffset + 2 * p1Index + 1]); + vec2 p2 = vec2(elementData[pointsOffset + 2 * p2Index], + elementData[pointsOffset + 2 * p2Index + 1]); + vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index], + elementData[pointsOffset + 2 * p3Index + 1]); + + if(cubic_bezier_dis(localUV, p0, p1, p2, p3)<=strokeWidth) + elementColor = vec4(1); + } + + elementBvhIndex = elementBvhLength; + } + else + { + // debugBVH.b += 0.2; + elementStack.push(elementBvhIndex); + elementBvhIndex = leftChild; + } + } + else + elementBvhIndex = elementBvhLength; + } + if (!elementStack.empty()) + { + elementStack.getTop(elementBvhIndex); + elementStack.pop(); + elementBvhIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y; + } + } + return elementColor.xyz; } void main() { - //ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy); - ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); - uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r; - if(paintingIndex==0) - return; + //ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy); + ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); + uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r; + if(paintingIndex==0) + return; - imageStore(gMetallicRoughness, pixelLocation, vec4(0 /*金属度*/, 0.8 /*粗糙度*/, 0, 1)); + imageStore(gMetallicRoughness, pixelLocation, vec4(0 /*金属度*/, 0.8 /*粗糙度*/, 0, 1)); - vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; + vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; - vec3 debugBVH = vec3(0); - bool debugHit = false; - stack.top = 0; - uint index = 0, visitTime = 0; - uint bvhLength = paintingOffsets[paintingIndex-1].y; - while (index < bvhLength || !stack.empty()) - { - while (index < bvhLength) - { - visitTime++; - vec4 bound = bvhBound[index]; - uint leftChild = bvhChildren[index].x; - if (leftChild >= bvhLength) - { - uint zIndex = bvhChildren[index].y / 65535; - float angle = (bvhChildren[index].y / 65535. - zIndex) * 2 * PI; + vec3 debugBVH = vec3(0); + bool debugHit = false; + stack.top = 0; + uint index = 0, visitTime = 0; + uint bvhLength = paintingOffsets[paintingIndex-1].y; + while (index < bvhLength || !stack.empty()) + { + while (index < bvhLength) + { + visitTime++; + vec4 bound = bvhBound[index]; + uint leftChild = bvhChildren[index].x; + if (leftChild >= bvhLength) + { + uint zIndex = bvhChildren[index].y / 65535; + float angle = (bvhChildren[index].y / 65535.0 - zIndex) * 2 * PI; - mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}}; - vec2 localUV = uv - (bound.xy + bound.zw) / 2; - localUV = rotation * localUV; - localUV /= (bound.zw - bound.xy) / 2; - if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1)))) - { - if (zIndex == 1) - debugBVH = vec3(1, 0, 1); - uint elementIndex = leftChild - bvhLength; - debugBVH.bg += 0.5 * (localUV + vec2(1)); + mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}}; + vec2 localUV = uv - (bound.xy + bound.zw) / 2; + localUV = rotation * localUV; + localUV /= (bound.zw - bound.xy) / 2; + if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1)))) + { + if (zIndex == 1) + debugBVH = vec3(1, 0, 1); + uint elementIndex = leftChild - bvhLength; + debugBVH.bg += 0.5 * (localUV + vec2(1)); - debugBVH = vec3(0); - debugHit = drawElement(leftChild - bvhLength, localUV, debugBVH) == vec3(1); - - } + debugBVH = vec3(0); + debugHit = drawElement(leftChild - bvhLength, localUV, debugBVH) == vec3(1); + + } - index = bvhLength; - } - else if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw))) - { - debugBVH.r += 0.02; - stack.push(index); - index = leftChild; - } - else - index = bvhLength; - } - if (!stack.empty()) - { - stack.getTop(index); - stack.pop(); - index = bvhChildren[index].y; - } - } + index = bvhLength; + } + else if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw))) + { + debugBVH.r += 0.02; + stack.push(index); + index = leftChild; + } + else + index = bvhLength; + } + if (!stack.empty()) + { + stack.getTop(index); + stack.pop(); + index = bvhChildren[index].y; + } + } - if (debugHit) - imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1)); - else - imageStore(gBaseColor, pixelLocation, vec4(debugBVH,1)); + if (debugHit) + imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1)); + else + imageStore(gBaseColor, pixelLocation, vec4(debugBVH,1)); } \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/shadow_mapping.comp b/ArchitectureColoredPainting/Shaders/shadow_mapping.comp new file mode 100644 index 0000000..ddd95c0 --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/shadow_mapping.comp @@ -0,0 +1,177 @@ +#version 450 core + +layout (local_size_x = 8, local_size_y = 8) in; + +uniform sampler2D gBaseColor; +uniform sampler2D gNormal; +uniform sampler2D gPosition; +uniform sampler2D gMetallicRoughness; +uniform sampler2DArray gShadowMap; +layout(rgba16f, binding = 1) uniform image2D gDirectLight; +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; +uniform mat4 view; +uniform float farPlane; +uniform float shadowCascadePlaneDistances[16]; +uniform float shadowBiases[16]; +uniform int shadowCascadeCount; + +uniform vec3 mainLightDirection; +uniform vec3 mainLightRadiance; + +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); +} + +float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer) +{ + // select cascade layer + vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0); + float depthValue = abs(fragPosViewSpace.z); + + layer = -1; + for (int i = 0; i < shadowCascadeCount; ++i) + { + if (depthValue < shadowCascadePlaneDistances[i]) + { + layer = i; + break; + } + } + if (layer == -1) + { + layer = shadowCascadeCount; + } + + int pcfRadius = 3; + float normalBias = 4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x; + vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0); + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; + + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + + // keep the shadow at 0.0 when outside the far_plane region of the light's frustum. + if (currentDepth > 1.0) + { + return 0.0; + } + + // PCF + float shadow = 0.0; + vec2 texelSize = 1.0 / vec2(textureSize(gShadowMap, 0)); + for(int x = -pcfRadius; x <= pcfRadius; ++x) + { + for(int y = -pcfRadius; y <= pcfRadius; ++y) + { + float pcfDepth = texture(gShadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r; + shadow += currentDepth > pcfDepth ? 1.0 : 0.0; + } + } + shadow /= (2*pcfRadius+1)*(2*pcfRadius+1); + + return shadow; +} + +void main() +{ + ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); + + vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r; + float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g; + + vec3 worldPos = texelFetch(gPosition, pixelLocation,0).xyz; + vec3 normal = texelFetch(gNormal, pixelLocation,0).xyz; + + 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)); + return; + } + + + vec3 V = normalize(camPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // calculate 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(normal, H, roughness); + float G = GeometrySmith(normal, 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(normal, V), 0.0) * max(dot(normal, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + float NdotL = max(dot(normal, L), 0.0); + vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL; + + int debugLayer; + float shadow = ShadowCalculation(worldPos, normal, debugLayer); + + imageStore(gDirectLight, pixelLocation, vec4((1-shadow)*Lo, 1)); +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/ssgi.comp b/ArchitectureColoredPainting/Shaders/ssgi.comp new file mode 100644 index 0000000..5bf0709 --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/ssgi.comp @@ -0,0 +1,413 @@ +#version 450 core + +layout (local_size_x = 8, local_size_y = 8) in; + +layout(rgba16f, binding = 1) uniform image2D gIndirectLight; + +uniform sampler2D gBaseColor; +uniform sampler2D gNormal; +uniform sampler2D gPosition; +uniform sampler2D gMetallicRoughness; +uniform sampler2D gDepth; +uniform sampler2D gDirectLight; + +uniform float u_Near = 10; +uniform float u_Far = 5000; +uniform vec3 camPos; +uniform mat4 cameraMatrix; +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; + +uniform vec3 mainLightDirection; +uniform vec3 mainLightRadiance; + +#define PI 3.14159265359 +#define HIZ_START_LEVEL 0 +#define HIZ_STOP_LEVEL 0 +#define HIZ_MAX_LEVEL 6 +#define MAX_ITERATIONS 60 + +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); +} + +vec3 mainLightRadianceCalculation(ivec2 fragPos, vec3 targetWorldPos, vec3 worldPos) +{ + if(texelFetch(gDirectLight, fragPos, 0).rgb==vec3(0)) + return vec3(0); + vec3 albedo = pow(texelFetch(gBaseColor, fragPos, 0).rgb, vec3(2.2)); + vec3 normal = texelFetch(gNormal, fragPos, 0).xyz; + float metallic = texelFetch(gMetallicRoughness, fragPos, 0).r; + float roughness = texelFetch(gMetallicRoughness, fragPos, 0).g; + + vec3 V = normalize(targetWorldPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // calculate light radiance + vec3 L = normalize(mainLightDirection); + vec3 H = normalize(V + L); + + vec3 radiance = mainLightRadiance ; + + // cook-torrance brdf + float NDF = DistributionGGX(normal, H, roughness); + float G = GeometrySmith(normal, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(normal, V), 0.0) * max(dot(normal, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + float NdotL = max(dot(normal, L), 0.0); + return (kD * albedo / PI + specular) * radiance * NdotL; +} + +vec3 indirectLightRadianceCalculation(ivec2 fragPos, vec3 lightPos, vec3 lightRadiance) +{ + //if(texelFetch(gDirectLight, fragPos, 0).rgb!=vec3(0)) + // return vec3(0); + vec3 albedo = pow(texelFetch(gBaseColor, fragPos, 0).rgb, vec3(2.2)); + vec3 worldPos = texelFetch(gPosition, fragPos, 0).xyz; + vec3 normal = texelFetch(gNormal, fragPos, 0).xyz; + float metallic = texelFetch(gMetallicRoughness, fragPos, 0).r; + float roughness = texelFetch(gMetallicRoughness, fragPos, 0).g; + + vec3 V = normalize(camPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // calculate light radiance + vec3 L = normalize(lightPos - worldPos); + vec3 H = normalize(V + L); + float distance = length(lightPos - worldPos); + float attenuation = 1.0 / (distance * distance); + vec3 radiance = lightRadiance * attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(normal, H, roughness); + float G = GeometrySmith(normal, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + //float NdotL = max(dot(normal, L), 0.0); + return kD * radiance; + //return kD * albedo * radiance* (dot(normal, L)>0?1:0); + //return (kD * albedo / PI ) * radiance * NdotL; +} + +float LinearizeDepth(float vDepth) +{ + float z = vDepth * 2.0 - 1.0; + return (2.0 * u_Near * u_Far) / (u_Far + u_Near - z * (u_Far - u_Near)); +} + +struct Ray +{ + vec3 o; + vec3 d; +}; + +struct ScreenSpaceRay +{ + vec3 o; + vec3 d; + float tmax; +}; + +struct SSTraceRecord +{ + Ray ray; + float tmax; +}; + +struct HitRecord +{ + float t; + vec2 pixel; +}; + + +vec3 projectToViewSpace(vec3 vPointInViewSpace) +{ + return vec3(viewMatrix * vec4(vPointInViewSpace,1)); +} +vec4 projectToScreenSpace(vec3 vPoint) +{ + return projectionMatrix * vec4(vPoint,1); +} +vec3 ndcToPixel(vec4 p) +{ + vec3 pos = p.xyz/p.w; + pos= (pos+1)/2; + pos.xy*=textureSize(gBaseColor,0); + //pos.z = -LinearizeDepth(pos.z); + //pos.z = -(pos.z); + return pos; +} + + +bool testHit(vec3 p, int level) +{ + //float sampleDepth = -LinearizeDepth(texelFetch(gDepth, ivec2(p.xy/exp2(level)) ,level).r); + //return p.z < sampleDepth && sampleDepth-p.z<50; + float sampleDepth = (texelFetch(gDepth, ivec2(p.xy/exp2(level)) ,level).r); + return p.z > sampleDepth; +} + +ScreenSpaceRay create_ss_ray(const Ray ray, float tmax) +{ + + vec3 p0 = projectToViewSpace(ray.o); + vec3 d = normalize(mat3(viewMatrix) * ray.d); + if(d.z > 0.0){ + tmax = min(tmax, abs(p0.z / d.z) * 0.999); + } + vec3 p1 = p0 + tmax * d; + p0 = ndcToPixel(projectToScreenSpace(p0)); + p1 = ndcToPixel(projectToScreenSpace(p1)); + ScreenSpaceRay ssray; + ssray.o = p0; + d = p1 - p0; + float len = length(d.xy); + ssray.d = d / len; + ssray.tmax = len; + return ssray; +} + +bool trace(const in SSTraceRecord record, inout HitRecord hit, inout vec3 debug) +{ + ivec2 screenSize = textureSize(gBaseColor,0); + ScreenSpaceRay ray = create_ss_ray(record.ray, record.tmax); + if(dot(ray.d, ray.d)< 1e-5){ + return false; + } + debug = vec3(normalize(vec2(ray.d.xy)), 0.0); + float march_step_base = 1.01; + vec3 dir = normalize(ray.d); + float t = 1.001; + ivec2 prev_pixel = ivec2(ray.o.xy); + int level = 0; + + int accum_level0_steps = 0; + + while(t < ray.tmax){ + float march_step = march_step_base; + for(int i =0;i ray.tmax || oob){ + if(level == 0) + break; + level--; + continue; + } + if(testHit(p, level)) { + if(level == 0){ + hit.t = next_t; + hit.pixel = p.xy; + return true; + } + level--; + continue; + }else{ + t = next_t; + } + if(level == 0){ + accum_level0_steps++; + }else{ + accum_level0_steps = 0; + } + if(level == 0){ + if(accum_level0_steps >= 8) { + level = min(level+1,HIZ_MAX_LEVEL); + } + }else{ + level = min(level+1,HIZ_MAX_LEVEL); + } + } + return false; +} + +void GetTangentSpace(vec3 normal, inout vec3 tangent, inout vec3 binormal) +{ + // Choose a helper vector for the cross product + vec3 helper = vec3(1, 0, 0); + if (abs(normal.x) > 0.99) + helper = vec3(0, 0, 1); + // Generate vectors + tangent = normalize(cross(normal, helper)); + binormal = normalize(cross(normal, tangent)); +} +float RandXY(float x, float y){ + return fract(cos(x * (12.9898) + y * (4.1414)) * 43758.5453); +} +uniform vec4 rdSeed; +float rdCnt=0; +float Rand(){ + float a = RandXY(gl_GlobalInvocationID.x, rdSeed[0]); + float b = RandXY(rdSeed[1], gl_GlobalInvocationID.y); + float c = RandXY(rdCnt++, rdSeed[2]); + float d = RandXY(rdSeed[3], a); + float e = RandXY(b, c); + float f = RandXY(d, e); + return f; +} +vec3 randomOnHemisphere(vec3 normal, float alpha) +{ + //p(w)=(α+1)/2π*cos^α + float theta = (2.0 * PI * Rand()); + float phi = acos(pow(Rand(), 1.0 / (alpha + 1.0))); + vec3 v = vec3((sin(phi) * cos(theta)), (sin(phi) * sin(theta)), cos(phi)); + + vec3 tangent, binormal; + GetTangentSpace(normal, tangent, binormal); + return vec3(dot(v, vec3(tangent.x, binormal.x, normal.x)), dot(v, vec3(tangent.y, binormal.y, normal.y)), dot(v, vec3(tangent.z, binormal.z, normal.z))); +} + + + + + + +void main() +{ + ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); + + vec3 worldPos = texelFetch(gPosition, pixelLocation,0).xyz; + vec4 viewPos = viewMatrix * vec4(worldPos,1); + vec3 normal = texelFetch(gNormal, pixelLocation,0).xyz; + + if(normal==vec3(0)) + { + imageStore(gIndirectLight, pixelLocation, vec4(0)); + return; + } + + //vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + vec3 ambient = vec3(0.03); + imageStore(gIndirectLight, pixelLocation, vec4(ambient,1)); + return; + vec3 color=vec3(0); + int spp=1; + for(int i=0;i0.95) + { + normal = vec3(0,1,0); + + + Ray ray; + ray.o = worldPos; + ray.d = normalize(reflect(worldPos-camPos, normal)); + SSTraceRecord traceRecord; + traceRecord.ray = ray; + traceRecord.tmax = 6000; + HitRecord hitRecord; + vec3 debug; + + bool Hit = trace(traceRecord, hitRecord, debug); + +// Ray ray; +// ray.Origin = worldPos; +// ray.Direction = normalize(reflect(worldPos-camPos, normal)); +// //ray.Direction = normalize(vec3(0,1,0)); +// ray.Origin += normal* (-viewPos.z / u_Far * 2 + 0.5); +// Result result = hiZTrace(ray); + //vec4 result = hiZTrace(pixelLocation, textureSize(gBaseColor, 0), worldPos, reflect(normalize(worldPos-camPos), normal)); + + if(Hit) + { + //imageStore(gIndirectLight, pixelLocation, vec4(1,0,0,1)); + imageStore(gIndirectLight, pixelLocation, pow(texelFetch(gBaseColor, ivec2(hitRecord.pixel), 0), vec4(2.2))); + } + else + imageStore(gIndirectLight, pixelLocation, vec4(1,1,0,1)); + //imageStore(gIndirectLight, pixelLocation, pow(texelFetch(gBaseColor, ivec2(result.UV), 0), vec4(2.2))); + return; + } + imageStore(gIndirectLight, pixelLocation, pow(texelFetch(gBaseColor, pixelLocation, 0), vec4(2.2))); + + + + +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/container.jpg b/ArchitectureColoredPainting/container.jpg deleted file mode 100644 index 50aa4c98631e6775ba37c5477196d03240823251..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122294 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

_4 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 Y)3t@?t1ruZn(~LPXxsi74gELse>&s2)&Kwi