Home › Forums › Games202-高质量实时渲染 › [作业1]关于PCSS边界明显的Tip
- This topic has 8 replies, 4 voices, and was last updated 3 years, 8 months ago by happyfire.
-
AuthorPosts
-
-
在完成PCSS的过程中,我的结果一直存在边界明显且部分区域过亮的问题(见图1),在群里好像也看到过类似的问题。其可能的原因是在求解PCF的filter size的时候,使用了normalized depth(范围[0,1])而不是linearized depth(view/eye space depth,范围[zNear, zFar])。修正后结果明显有所改善(见图2)。希望这个能对大家debug有所帮助:)
This post has received 3 votes up.Attachments:
You must be logged in to view attached files. -
linear depth计算:https://learnopengl.com/Advanced-OpenGL/Depth-testing
- This reply was modified 3 years, 8 months ago by JH.
-
夜影Participant
感谢大佬 我说怎么之前一直不对 传进来的点是经过投影变换的 而shadowmap上的点是正交投影出来的 肯定怎么算怎么错
-
请问能说清楚一些吗?最好能上代码。
PCF里面比较的是shadowmap中的深度和当前片段在LightSpace中的深度。这两个深度都是正交投影计算出来的吧,而且使用的都是LightMVP矩阵。
区别只是shadowmap中的深度是从gl_FragCoord.z读取出来的,这个值是range到了0~1(默认)。而用来和shadowmap比较的深度计算是vPositionFromLight = uLightMVP * vec4(aVertexPosition, 1.0);
这个就是clip space的,当然对于正交投影,w=1,因此就是NDC的。因此范围是[-1,1],因此只要转换到[0,1]就可以和shadow map解压出来的深度比较了。
如果我分析的没问题的话,这里面找不到需要变换到线性深度(eye space z,范围[n,f])的地方呀?而且用的都是一样的矩阵,即便不是正交投影,是透视投影,应该也没问题吧?另外最终出的效果和采样数,filterSize都有关系,你确定其他参数都没变?
-
Sorry,看成PCF了,不过意思一样的。(这个帖子不能编辑吗?没找到EDIT..)
findBlocker和PCF里面都是用的一样的z,可能你修改了findBlocker,不过这个函数真的是改一点东西影响都很大,所以你改了z应该就是会有不同的效果。但是我觉得应该和linear depth没关系的,请批评指正!-
不好意思我可能有点没说清楚…我的意思是修改PCSS中step2 penumbra size的计算,而所有关于shadow map中深度的比较都是用的[0,1]范围的深度这个没错。
这个是我原来的代码float filterSize = (coords.z / avgBlockerDepth - 1.0) * LIGHT_WIDTH_UV; float ret = PCF(shadowMap, coords, filterSize);
其中coord.z和avgBlockerDepth都是[0,1]的值。
这个是我更新后的代码float vsReceiverDepth = linearizeDepth(coords.z); float vsBlockerDepth = linearizeDepth(avgBlockerDepth); float filterSize = (vsReceiverDepth / vsBlockerDepth - 1.0) * LIGHT_WIDTH_UV; float ret = PCF(shadowMap, coords, filterSize);
简单来说就是把这里normalized的depth转换到linear depth再求解filterSize。我非常同意你说的有可能改一点就会让结果差很多,比如你可以加一个scalar来进行调参,不过这样并不能保证是physically correct的。我的理解是求解filterSize的本质是相似三角形,不过当所有距离都进行来非线性变换(从linear depth变成[0,1])之后相似三角形的比例关系并不能保证一定满足,所以这里利用linear depth求解是比较合理的。实践上来看我自己的测试也得到了更好的效果,同时我也参考了一些别人的实现,包括Nvidia的实现(http://developer.download.nvidia.com/whitepapers/2008/PCSS_Integration.pdf),感觉大多都是使用linear depth来计算的。
这些就是我大致的理解和推测,如果有问题的话欢迎继续讨论:)-
了解了,你应该是用了透视投影,然后你的zReceiver和zBlocker都不是线性的,所以你需要转到线性吧。这没问题。
我是跟着课程走的,计算penumbra就是用的一个简单的相似三角形,当然用的是正交投影,所以zReceiver和zBlocker都是线性的,因此这么计算:
float penumbra = (zReceiver – zBlocker) * LIGHT_WIDTH / zBlocker;
应该没有物理上不正确吧
-
-
-
-
shengjieParticipant
如果你用的是正交投影矩阵,深度就是线性的,虽然数值范围需要从[-1,1]变换到[0,1]。看你的描述,你是用了perspective projection?
findBlock的搜索范围确实应该设大一点。但step2-3 z的绝对值不重要,只要z是线性的,求相似三角形比值只和z的相对值有关。
我认为其他的坑点在
1.8个uint表示float的数值精度问题
2.地板自遮挡
需要好好调参一下eps-
我觉得你说有道理,而且directional light也应该是用正交投影,所以不需要去做linearization。我这里的操作应该只能针对使用透视投影的光源。感谢指正!
-
-
-
AuthorPosts
- You must be logged in to reply to this topic.