改用论文的分割方案,实现画线

dev-VirtualTexture
wuyize 2022-09-06 16:37:48 +08:00
parent ddff01d880
commit fa112820cc
12 changed files with 1521 additions and 489 deletions

View File

@ -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" />

View File

@ -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">

View File

@ -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>

View File

@ -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),
QVector4D(-1,-1,-0.2,1), QVector4D(-0.2,-1,1,1),
//elememt1
QVector4D(-1,0,1,1),
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,

View File

@ -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);

View File

@ -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;

View File

@ -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));
}

View File

@ -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;
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;

View File

@ -31,9 +31,8 @@ layout(std430, binding = 4) buffer elementOffsetBuffer
** @[1] elementBvhLength
** @[2] pointsOffset
** @[3] linesOffset
** @[4] contoursOffset
**********************/
uint elementOffset[][5];
uint elementOffset[][4];
};
layout(std430, binding = 5) buffer elementIndexBuffer
{
@ -252,17 +251,462 @@ int cubic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
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)<eps){
// /* no absolute term: y(y^3 + py + q) = 0 */
// vec3 cubic_coeffs;
// cubic_coeffs[0] = q;
// cubic_coeffs[1] = p;
// cubic_coeffs[2] = 0.;
// num = solve_cubic(cubic_coeffs, s.xyz);
// s[num] = 0.;
// num++;
//}
{
/* solve the resolvent cubic ... */
vec3 cubic_coeffs;
cubic_coeffs[0] = 1.0/2. * r * p - 1.0/8. * q * q;
cubic_coeffs[1] = - r;
cubic_coeffs[2] = - 1.0/2. * p;
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];
}
}
}
/* 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<halley_iterations;j++){
roots[i] = halley_iteration5(b0,b1,b2,b3,b4,roots[i]);
}
//compute squared distance to nearest point on curve
roots[i] = clamp(roots[i],0.,1.);
vec2 to_curve = uv - parametric_cub_bezier(roots[i],p0,p1,p2,p3);
d0 = min(d0,dot(to_curve,to_curve));
}
}
return sqrt(d0);
}
vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
{
vec4 elementColor = vec4(0);
uint currentOffset[5] = elementOffset[elementIndex];
uint currentOffset[4] = elementOffset[elementIndex];
uint elementBvhRoot = currentOffset[0];
uint elementBvhLength = currentOffset[1];
uint pointsOffset = currentOffset[2];
uint linesOffset = currentOffset[3];
uint contoursOffset = currentOffset[4];
elementStack.top = 0;
uint elementBvhIndex = 0;
@ -288,10 +732,9 @@ vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
uint num_its = 0;
uint contourIterator = contoursOffset + contourIndex*3;
if(elementIndexs[contourIterator]==elementIndexs[contourIterator+1])
contourIterator++;
for (;contourIterator < contoursOffset + contourIndex*3 + 3; contourIterator++)
uint lineCount = elementIndexs[contourIndex];
for ( uint contourIterator = contourIndex + 1;contourIterator < contourIndex + 1 + lineCount; contourIterator++)
{
uint lineIndex = elementIndexs[contourIterator];
uint p0Index = elementIndexs[linesOffset + 4 * lineIndex];
@ -325,6 +768,24 @@ vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
}
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];
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;
@ -377,7 +838,7 @@ void main()
if (leftChild >= bvhLength)
{
uint zIndex = bvhChildren[index].y / 65535;
float angle = (bvhChildren[index].y / 65535. - zIndex) * 2 * PI;
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;

View File

@ -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));
}

View File

@ -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