Lskyi
@Lskyi
Lskyi
@Lskyi
-
强推,唯一问题就是大二下计算机专业课程安排有点集中,我去年选修选了 ICS 汇编语言 面向对象,然后又包括英语体育数学建模,最后前 8 周平均每周 21 节课(不算周末上机实验的话),有毅力的可以尝试复刻。
Post #6 -
看文档我觉得需要格外注意 一条边界 (a boundary) 和 一条边界边 (a boundary edge) 概念的区别,dandelion 中,一条边界上的所有边共享一个 virtual face
举个例子就是,一个立方体上有一个洞,洞口由 20 条 boundary edge 构成,那么这个洞对应一个 virtual face,而这 20 条边靠近洞一侧的 20 条半边首尾相连成环,都隶属于那一个 virtual face。
这也说明,一个 boundary halfedge 的 prev 和 next 是相邻的 boundary halfedge。
你的代码中,boundary halfedge 的 next 和 prev 都成了自身了,这肯定是错的。建议使用 validate() 函数,检查自己操作完还符不符合半边网络数据结构。
Post #2 -
打印 122 和 123 之间是多线程程序,这意味着你的错误可能出现在 vertexshader rasterizer phongshader 三个线程中的任意一个线程上。
建议用 debugger 使用 backtrace 查看调用堆栈排查是哪里出错。
一个常见可能出错的地在 FragmentProcessor::worker_thread 里有个 framebuffer->set_pixel(index,fragment.depth,fragment.color); 这个需要你确保你输出的片元的 index 控制在合法范围内。Post #2 ❤️ 2 likes -
depth_buffer 初值是 inf,说明这个地方没有任何东西,所以出现 inf 很正常
其实深度映射集中问题也不大,你可以把光源相机渲染的深度图打出来看看实际是什么样,我的光源相机 far_plane 只设置成了 200.0f,看起来都够用。

后面的图看起来有点像 shadow acne 的问题,需要调整 shadow bias,也可以使用根据光源和法线角度(注意法线插值问题)动态调整 bias 算法之类的。此外提高深度图分辨率也可以。
但最主要是你第一张图 cube 上都看不到 cow 的影子,我觉得你应该先把影子效果做出来再看失真问题。Post #2 -
这处死循环可能是因为你在尝试 collapse 一条已经被 erase 过的边,因为我遇到过。
具体来说,在你的代码中,一次 collapse_edge(e) 会 erase 包括 e 在内总计 3 条 edge,那如果除了 e 之外,另外两条边也在 selected_edge 里的话,就会出现这个错误。
此外,这种错误靠 validate() 检查不出来,因为它本身已经不在网格里了。Post #2 -
曲面细分对于 cube 有个整体往回缩的趋势,八个顶点突出考虑是因为旧顶点坐标计算错了往回缩的不够多。可能要看下更新顺序问题?比如要在对每条边分裂之前先计算旧顶点新坐标。
对于新顶点的计算,如果你是将所有边分裂完之后再用你现在的算法,你应该注意到由于旁边的边已经分裂,在半边网络数据里产生了新顶点,公式里的 v3 和 v4 两个顶点与新顶点已经不邻接,你的 V3addV4 可能变成了相邻的两个新顶点相加,你应该在分裂前就计算。Post #2 -
从 Eigen C5054 警告不难发现你没有升级到 dandelion 1.1.1 版本,dandelion1.1.1 同步更新的
CompilerFlags.cmake文件对编译选项进行了调整,使得浮点隐式转换为 int 的警告被视为错误。Post #3 -
而且不难发现如果改了 CMakeLists.txt 里的
#debug dandelion-ray-debug #optimized dandelion-ray链接库,并且在 utils/ray.cpp 里的generate_ray函数在实验中没有正确实现,也会影响结果。Post #5 ❤️ 1 like -
我反汇编了自己.exe 程序发现了极为类似的代码

不过我在程序运行中还从来没有进入死循环但是 考虑到可能是 input_vertices() 速度过快,导致从来没有进入到循环的第一个判断代码块,于是我在 RasterizerRenderer::render()(也就是渲染主线程)中,在拉起 worker 到开始 input 顶点之间,加入了 std::this_thread::sleep_for(std::chrono::seconds(2)); 这确保了 vertex_woker 存在至少一次判空的情况。
然后复现了你遇到的 bug,程序无响应
这个数据竞争问题可以说是相当惊人,这么看不上锁情况下对一个队列判空在 O3 下是一个不可接受的操作。实际上,我后来发现遇到的问题给队列判空加锁也可以解决,不需要修改头文件,但从这不难看出,在 O3 下使用多线程共享简单变量使用 std::atomic 应该是最佳实践。
此外,原项目代码给我一种不想频繁上锁(忙等)降低性能的感觉,但这种做法在 O3 下运行似乎不是那么一回事。
Post #3 ❤️ 2 likes