diff --git a/ArchitectureColoredPainting/Light.cpp b/ArchitectureColoredPainting/Light.cpp index 72ee815..a0a75ba 100644 --- a/ArchitectureColoredPainting/Light.cpp +++ b/ArchitectureColoredPainting/Light.cpp @@ -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 Light::getLightSpaceMatrices() { std::vector 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; diff --git a/ArchitectureColoredPainting/Light.h b/ArchitectureColoredPainting/Light.h index 553b9f9..12ffbc2 100644 --- a/ArchitectureColoredPainting/Light.h +++ b/ArchitectureColoredPainting/Light.h @@ -14,6 +14,7 @@ class Light public: QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized(); std::vector shadowCascadeLevels; + float blendRatio = 0.3; std::vector frustumSizes; Model* model; Light(Camera* camera); diff --git a/ArchitectureColoredPainting/MainWindow.cpp b/ArchitectureColoredPainting/MainWindow.cpp index 9b97b34..1f7025b 100644 --- a/ArchitectureColoredPainting/MainWindow.cpp +++ b/ArchitectureColoredPainting/MainWindow.cpp @@ -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() diff --git a/ArchitectureColoredPainting/MainWindow.ui b/ArchitectureColoredPainting/MainWindow.ui index cdb031a..06b2055 100644 --- a/ArchitectureColoredPainting/MainWindow.ui +++ b/ArchitectureColoredPainting/MainWindow.ui @@ -6,7 +6,7 @@ 0 0 - 600 + 800 400 @@ -14,9 +14,71 @@ MainWindow + + + 0 + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + - + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + + + + + + + 0 + 0 + + + + 180 + + + Qt::Horizontal + + + + + + + 360 + + + Qt::Horizontal + + + + + + diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp index 31149b6..0155282 100644 --- a/ArchitectureColoredPainting/Model.cpp +++ b/ArchitectureColoredPainting/Model.cpp @@ -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 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 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(children.begin()+2, children.end()), bounds, diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp index 36b6d9e..b3220d7 100644 --- a/ArchitectureColoredPainting/RendererWidget.cpp +++ b/ArchitectureColoredPainting/RendererWidget.cpp @@ -7,6 +7,10 @@ #include #include +//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()); 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(); } diff --git a/ArchitectureColoredPainting/RendererWidget.h b/ArchitectureColoredPainting/RendererWidget.h index 0ceeb9f..c88efb9 100644 --- a/ArchitectureColoredPainting/RendererWidget.h +++ b/ArchitectureColoredPainting/RendererWidget.h @@ -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; diff --git a/ArchitectureColoredPainting/Shaders/painting.comp b/ArchitectureColoredPainting/Shaders/painting.comp index 83b23b8..71db44c 100644 --- a/ArchitectureColoredPainting/Shaders/painting.comp +++ b/ArchitectureColoredPainting/Shaders/painting.comp @@ -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 - 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)); + 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,8 +804,22 @@ 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)); diff --git a/ArchitectureColoredPainting/Shaders/shadow_mapping.comp b/ArchitectureColoredPainting/Shaders/shadow_mapping.comp index ddd95c0..6e6c592 100644 --- a/ArchitectureColoredPainting/Shaders/shadow_mapping.comp +++ b/ArchitectureColoredPainting/Shaders/shadow_mapping.comp @@ -16,7 +16,8 @@ uniform mat4 view; uniform float farPlane; uniform float shadowCascadePlaneDistances[16]; uniform float shadowBiases[16]; -uniform int shadowCascadeCount; +uniform int shadowCascadeCount; +uniform float shadowBlendRatio; uniform vec3 mainLightDirection; uniform vec3 mainLightRadiance; @@ -64,29 +65,10 @@ 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; + 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; @@ -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; }