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