Compare commits

...

2 Commits

9 changed files with 216 additions and 64 deletions

View File

@ -14,7 +14,7 @@ Light::Light(Camera* camera)
+ (1 - lambda) * (camera->NearPlane + i / levelCount * (camera->FarPlane - camera->NearPlane)));
//qDebug() << shadowCascadeLevels[i-1];
}
shadowCascadeLevels.push_back(camera->FarPlane);
}
@ -127,19 +127,19 @@ std::vector<QMatrix4x4> Light::getLightSpaceMatrices()
{
std::vector<QMatrix4x4> ret;
frustumSizes.clear();
for (size_t i = 0; i < shadowCascadeLevels.size() + 1; ++i)
for (size_t i = 0; i < shadowCascadeLevels.size(); ++i)
{
if (i == 0)
{
ret.push_back(getLightSpaceMatrix(camera->NearPlane, shadowCascadeLevels[i]));
}
else if (i < shadowCascadeLevels.size())
else if (i == 1)
{
ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], shadowCascadeLevels[i]));
ret.push_back(getLightSpaceMatrix((1 - blendRatio) * shadowCascadeLevels[i - 1] + blendRatio * camera->NearPlane, shadowCascadeLevels[i]));
}
else
{
ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], camera->FarPlane));
ret.push_back(getLightSpaceMatrix((1 - blendRatio) * shadowCascadeLevels[i - 1] + blendRatio * shadowCascadeLevels[i - 2], shadowCascadeLevels[i]));
}
}
return ret;

View File

@ -14,6 +14,7 @@ class Light
public:
QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized();
std::vector<float> shadowCascadeLevels;
float blendRatio = 0.3;
std::vector<float> frustumSizes;
Model* model;
Light(Camera* camera);

View File

@ -1,9 +1,15 @@
#include "MainWindow.h"
#include "RendererWidget.h"
#include "qslider.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QObject::connect(ui.horizontalSlider, &QSlider::valueChanged,
ui.openGLWidget, &RendererWidget::setMainLightPitch);
QObject::connect(ui.horizontalSlider_2, &QSlider::valueChanged,
ui.openGLWidget, &RendererWidget::setMainLightYaw);
}
MainWindow::~MainWindow()

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<width>800</width>
<height>400</height>
</rect>
</property>
@ -14,9 +14,71 @@
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="RendererWidget" name="openGLWidget"/>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="RendererWidget" name="openGLWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>180</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_2">
<property name="maximum">
<number>360</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -114,6 +114,12 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
processNode(node->mChildren[i], scene, mat4 * node->mChildren[i]->mTransformation);
}
}
GLuint encodeChild(GLuint index)
{
return 0x80000000 + index;
}
Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
@ -188,12 +194,12 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
//root
1,2,
3,4, 5,6,
7,0, 7,GLuint(30. / 360 * 65536 + 1 * 65536) /*右儿子用来表示旋转角度和zIndex*/, 8,0, 7,0,
encodeChild(0),0, encodeChild(0),GLuint(30. / 360 * 65536 + 1 * 65536) /*右儿子用来表示旋转角度和zIndex*/, encodeChild(1),0, encodeChild(0),0,
//elememt0
1,2,
3 + 20/*contour索引由于contour不定长这里需要给到contour在elementIndex中位置*/,3 + 14/*style索引在elementData中位置*/, 3+24,3+14,
encodeChild(20)/*contour索引由于contour不定长这里需要给到contour在elementIndex中位置*/,14/*style索引在elementData中位置*/, encodeChild(24), 14,
//elememt1
1 + 0/*line索引element中第几条*/,1 + 27
encodeChild(0)/*line索引element中第几条*/, 27
};
std::vector<QVector4D> bvhBounds = {
@ -205,7 +211,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
QVector4D(-1,-1,1,1),
QVector4D(-1,-1,-0.2,1), QVector4D(-0.2,-1,1,1),
//elememt1
QVector4D(-1,0,1,1)
QVector4D(-1,-1,1,1)
};
std::vector<GLuint> elementOffset = {
//element0
@ -250,7 +256,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
//element1
//points
-1,0.5, 0,1, 1,0.5,
0,0.8, 1,0, 0,-0.8,
//strokeStyle
//stroke
1,
@ -260,8 +266,14 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
0, //Ô²½Ç
//strokeFillType
0, //µ¥É«
//线类型
1, //左侧
//线外描边宽度
0,
//线外描边方式
0, //单色
//strokeFillColorMetallicRoughness
0,1,0, 0,0.8
1,0,1, 0,0.8
};
//m_mesh->paintingIndex = paintingHelper->addPainting(bounds.size(), std::vector<GLuint>(children.begin()+2, children.end()), bounds,

View File

@ -7,6 +7,10 @@
#include <QGuiApplication>
#include <random>
//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;
RendererWidget::RendererWidget(QWidget* parent)
: QOpenGLWidget(parent)
@ -47,6 +51,17 @@ RendererWidget::~RendererWidget()
}
}
void RendererWidget::setMainLightPitch(float pitch)
{
//qDebug() << "pitch" << pitch;
sunPitch = pitch;
}
void RendererWidget::setMainLightYaw(float yaw)
{
//qDebug() << "yaw" << yaw;
sunYaw = yaw;
}
QOpenGLTexture randomMap(QOpenGLTexture::Target2D);
void RendererWidget::initializeGL()
{
@ -190,6 +205,7 @@ void RendererWidget::initializeGL()
paintingHelper = new PaintingHelper(QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Compatibility>());
model = new Model("Models/Sponza/Sponza.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
//model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
light.model = model;
qDebug() << model->AABB;
@ -226,10 +242,7 @@ 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 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()
{
light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw)));
@ -309,6 +322,7 @@ void RendererWidget::paintGL()
shadowMappingProgramPtr->setUniformValueArray("shadowBiases", light.frustumSizes.data(), light.frustumSizes.size(), 1);
//qDebug() << light.frustumSizes;
shadowMappingProgramPtr->setUniformValue("shadowCascadeCount", (GLint)light.shadowCascadeLevels.size());
shadowMappingProgramPtr->setUniformValue("shadowBlendRatio", light.blendRatio);
shadowMappingProgramPtr->setUniformValue("camPos", camera.Position);
shadowMappingProgramPtr->setUniformValue("mainLightDirection", light.lightDirection);
shadowMappingProgramPtr->setUniformValue("mainLightRadiance", lightColors[0]);
@ -379,8 +393,8 @@ void RendererWidget::paintGL()
void RendererWidget::resizeGL(int width, int height)
{
frameWidth = devicePixelRatioF() * width;
frameHeight = devicePixelRatioF() * height;
frameWidth = ceil( devicePixelRatioF() * width);
frameHeight = ceil(devicePixelRatioF() * height);
qDebug() << frameWidth << "x" << frameHeight;
camera.Ratio = (float)frameWidth / (float)frameHeight;
//qDebug() << devicePixelRatioF() << width << height;
@ -492,7 +506,7 @@ void RendererWidget::resizeGL(int width, int height)
//Depth
glBindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
glTexImage3D(
GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, shadowMapResolution, shadowMapResolution, int(light.shadowCascadeLevels.size()) + 1,
GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, shadowMapResolution, shadowMapResolution, int(light.shadowCascadeLevels.size()),
0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
/*glBindTexture(GL_TEXTURE_2D, shadowGbuffer);
@ -565,12 +579,12 @@ void RendererWidget::timerEvent(QTimerEvent* event)
}
sunPitch += sunSpeed * deltaTime;
/*sunPitch += sunSpeed * deltaTime;
if (sunPitch > 120 || sunPitch < 65)
{
sunSpeed = -sunSpeed;
sunPitch += sunSpeed * deltaTime;
}
}*/
repaint();
}

View File

@ -19,6 +19,9 @@ public:
RendererWidget(QWidget* parent = nullptr);
~RendererWidget();
public slots:
void setMainLightPitch(float pitch);
void setMainLightYaw(float yaw);
protected:
void initializeGL() override;
void paintGL() override;

View File

@ -486,7 +486,7 @@ int solve_quartic(vec4 coeffs, inout vec4 s){
return num;
}
float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3){
float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEnd){
//switch points when near to end point to minimize numerical error
//only needed when control point(s) very far away
@ -689,18 +689,32 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3){
//compute squared distance to nearest point on curve
if(roundEnd)
{
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));
}
else
{
if(roots[i]<0.||roots[i]>1.) d0=min(d0,1e38);
else
{
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))
bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, inout vec3 debugBVH = vec3(0))
{
vec4 elementColor = vec4(0);
bool hitElement = false;
vec4 elementColor = vec4(-1);
uint currentOffset[4] = elementOffset[elementIndex];
uint elementBvhRoot = currentOffset[0];
@ -724,11 +738,11 @@ vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
{
debugBVH.g += 0.5;
uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y - elementBvhLength;
uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y;
// for(int i = 0; i<200;i++)
if (elementData[styleIndex] == 0.) //Ãæ
{
uint contourIndex = leftChild - elementBvhLength;
uint contourIndex = leftChild - 0x80000000;
uint num_its = 0;
@ -760,16 +774,22 @@ vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
num_its += cubic_bezier_int_test(localUV, p0, p1, p2, p3);
}
if (num_its % 2 == 1)
if (num_its % 2 == 1 && elementColor.a<1)
{
elementColor = vec4(1);
//debugHit = true;
hitElement = true;
elementColor = vec4(1,1,0,0);
if(elementData[styleIndex+1]==0)
{
elementColor = vec4(elementData[styleIndex+2],elementData[styleIndex+3],elementData[styleIndex+4],0);
}
}
}
else if (elementData[styleIndex] == 1) //Ïß
{
float strokeWidth = elementData[styleIndex+1];
uint lineIndex = leftChild - elementBvhLength;
uint lineIndex = leftChild - 0x80000000;
uint p0Index = elementIndexs[linesOffset + 4 * lineIndex];
uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1];
uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2];
@ -784,9 +804,23 @@ vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index],
elementData[pointsOffset + 2 * p3Index + 1]);
if(cubic_bezier_dis(localUV, p0, p1, p2, p3)<=strokeWidth)
float lineType = elementData[styleIndex+4];
/*if(cubic_bezier_dis(localUV, p0, p1, p2, p3, true)<=0.001)
{
hitElement = true;
elementColor = vec4(1);
}
else */if(cubic_bezier_dis(localUV, p0, p1, p2, p3, elementData[styleIndex+2]==0)<=strokeWidth
&&(lineType==2 ||cubic_bezier_int_test(localUV, p0, p1, p2, p3)==lineType))
{
hitElement = true;
elementColor = vec4(1);
if(elementData[styleIndex+3]==0)
{
elementColor = vec4(elementData[styleIndex+7],elementData[styleIndex+8],elementData[styleIndex+9],1);
}
}
}
elementBvhIndex = elementBvhLength;
}
@ -807,7 +841,8 @@ vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
elementBvhIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y;
}
}
return elementColor.xyz;
color = elementColor.xyz;
return hitElement;
}
@ -824,7 +859,8 @@ void main()
vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
vec3 debugBVH = vec3(0);
bool debugHit = false;
//bool debugHit = false;
vec4 color = vec4(-1);
stack.top = 0;
uint index = 0, visitTime = 0;
uint bvhLength = paintingOffsets[paintingIndex-1].y;
@ -844,15 +880,17 @@ void main()
vec2 localUV = uv - (bound.xy + bound.zw) / 2;
localUV = rotation * localUV;
localUV /= (bound.zw - bound.xy) / 2;
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))))
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))) && zIndex>color.w)
{
if (zIndex == 1)
debugBVH = vec3(1, 0, 1);
uint elementIndex = leftChild - bvhLength;
//uint elementIndex = leftChild - bvhLength;
debugBVH.bg += 0.5 * (localUV + vec2(1));
debugBVH = vec3(0);
debugHit = drawElement(leftChild - bvhLength, localUV, debugBVH) == vec3(1);
vec3 elementColor;
if(drawElement(leftChild - 0x80000000, localUV, elementColor, debugBVH))
color = vec4(elementColor, zIndex);
}
@ -875,7 +913,9 @@ void main()
}
}
if (debugHit)
imageStore(gBaseColor, pixelLocation, vec4(color.rgb,1));
return;
if (color.a!=-1)
imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1));
else
imageStore(gBaseColor, pixelLocation, vec4(debugBVH,1));

View File

@ -17,6 +17,7 @@ uniform float farPlane;
uniform float shadowCascadePlaneDistances[16];
uniform float shadowBiases[16];
uniform int shadowCascadeCount;
uniform float shadowBlendRatio;
uniform vec3 mainLightDirection;
uniform vec3 mainLightRadiance;
@ -64,28 +65,9 @@ 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)
const int pcfRadius = 3;
float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,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
@ -114,7 +96,39 @@ float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer)
}
}
shadow /= (2*pcfRadius+1)*(2*pcfRadius+1);
return shadow;
}
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;
// }
float shadow = getShadowFromLayer(fragPosWorldSpace,normal,layer);
float nextLayerBeginDepth = layer==0? (1-shadowBlendRatio)*shadowCascadePlaneDistances[layer]
:(1-shadowBlendRatio)*shadowCascadePlaneDistances[layer]+shadowBlendRatio*shadowCascadePlaneDistances[layer-1];
if(depthValue > nextLayerBeginDepth)
{
float shadowNext = getShadowFromLayer(fragPosWorldSpace,normal,layer+1);
shadow = mix(shadow,shadowNext, (depthValue-nextLayerBeginDepth)/(shadowCascadePlaneDistances[layer]-nextLayerBeginDepth));
}
return shadow;
}