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 50aa4c9..0000000 Binary files a/ArchitectureColoredPainting/container.jpg and /dev/null differ