改用论文的分割方案,实现画线
parent
ddff01d880
commit
fa112820cc
|
@ -117,6 +117,8 @@
|
|||
<None Include="Shaders\painting.vert" />
|
||||
<None Include="Shaders\shader.frag" />
|
||||
<None Include="Shaders\shader.vert" />
|
||||
<None Include="Shaders\shadow_mapping.comp" />
|
||||
<None Include="Shaders\ssgi.comp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BvhTree.h" />
|
||||
|
|
|
@ -116,6 +116,12 @@
|
|||
<None Include="Shaders\model_shadow.geom">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="Shaders\shadow_mapping.comp">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="Shaders\ssgi.comp">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Camera.h">
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<file>Shaders/model.vert</file>
|
||||
<file>Shaders/final.frag</file>
|
||||
<file>Shaders/final.vert</file>
|
||||
<file>container.jpg</file>
|
||||
<file>Shaders/painting.frag</file>
|
||||
<file>Shaders/painting.vert</file>
|
||||
<file>Shaders/painting.comp</file>
|
||||
|
@ -15,5 +14,7 @@
|
|||
<file>Shaders/depth_mipmap.comp</file>
|
||||
<file>Shaders/depth_init.comp</file>
|
||||
<file>Shaders/model_shadow.geom</file>
|
||||
<file>Shaders/shadow_mapping.comp</file>
|
||||
<file>Shaders/ssgi.comp</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -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<QVector4D> 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<GLuint> 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<GLuint> 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<GLfloat> 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,
|
||||
|
|
|
@ -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,46 +226,29 @@ 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<QMatrix4x4> 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);
|
||||
|
@ -262,19 +278,16 @@ void RendererWidget::paintGL()
|
|||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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));
|
||||
}
|
|
@ -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<level;i++){
|
||||
march_step *= 1.6;
|
||||
}
|
||||
float next_t = t + march_step;
|
||||
|
||||
vec3 p = ray.o + ray.d * next_t;
|
||||
ivec2 pixel = ivec2(p.xy);
|
||||
bool oob = false;
|
||||
if(any(greaterThanEqual(pixel, screenSize)))
|
||||
oob = true;
|
||||
if(any(lessThan(pixel, ivec2(0))))
|
||||
oob = true;
|
||||
if(next_t > 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<w,n>^¦Á
|
||||
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;i<spp;i++)
|
||||
{
|
||||
|
||||
Ray ray;
|
||||
ray.o = worldPos;
|
||||
ray.d = normalize(randomOnHemisphere(normal, 1));
|
||||
SSTraceRecord traceRecord;
|
||||
traceRecord.ray = ray;
|
||||
traceRecord.tmax = 500;
|
||||
HitRecord hitRecord;
|
||||
vec3 debug;
|
||||
|
||||
bool Hit = trace(traceRecord, hitRecord, debug);
|
||||
|
||||
if(Hit)
|
||||
{
|
||||
vec3 hitWorldPos = texelFetch(gPosition, ivec2(hitRecord.pixel), 0).xyz;;
|
||||
vec3 lightRadiance = mainLightRadianceCalculation(ivec2(hitRecord.pixel), worldPos, hitWorldPos);
|
||||
vec3 indirectRadiance = indirectLightRadianceCalculation(pixelLocation, hitWorldPos, lightRadiance*10000);
|
||||
color+=indirectRadiance;
|
||||
|
||||
//color+= pow(texelFetch(gBaseColor, ivec2(result.UV), 0).rgb, vec3(2.2));
|
||||
}
|
||||
}
|
||||
imageStore(gIndirectLight, pixelLocation, vec4(color/spp, 1));
|
||||
return;
|
||||
|
||||
if(normal.y>0.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)));
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 119 KiB |
Loading…
Reference in New Issue