Page MenuHome

Cycles: rays miss triangles
Closed, ArchivedPublic

Description

System Information
OS: windows 7 64bit, CPU: i5-3550 GPU: ATI HD7850

Blender Version
2.75a c27589e

Short description of error
I found these reoprts connected to this problem: T34094 D819 rBf770bc4757a2b471d5aaee048359096c1c79a6b2 (rB9489205c5c0b9b432d02be4a3d0d15fc62ee6cb9)

I found that it seems to be a particular range of angle between faces in wich the rays are able to miss the triangles.
Fireflies or worse are the consequences.

Exact steps for others to reproduce the error
1.put the camera inside a cylinder (32 vertices)
2.rotate the cam so it is looking at the round part of the cylinder

  1. set the background shader strength to 5000

4.render it on 200 samples


It should show some fireflies all over the image.

File:


This problem occured to me on an extreme case as I built a sealing for a room.
I'll attach a simplified file of it:

btw. the "a" version of blender 2.75 has some problem with my GPU so I renderd with CPU.

Details

Type
Bug

Event Timeline

Felix (BOBtheROSS) raised the priority of this task from to Needs Triage by Developer.
Felix (BOBtheROSS) updated the task description. (Show Details)
Felix (BOBtheROSS) set Type to Bug.

Tried it on GPU. I also get the fireflies.
And I noticed: the bigger the cylinder, the more fireflies.

Thomas Dinges (dingto) lowered the priority of this task from Needs Triage by Developer to Normal.
Thomas Dinges (dingto) removed a project: Rendering.
Sergey Sharybin (sergey) closed this task as Archived.Sep 16 2015, 3:14 PM

There are two sources of issue:

  • Original watertight paper suggests fallback to double precision arithmetic when it's detected system determinant is zero. This gives some extra stability (of watertight-ness if you want) in cases when ray hits exact edge of a triangle.
  • BVH nodes intersection was never implemented to be watertight, which might cause missing ray-triangle checks all together if ray hits exact boundary of the node.

Here's a quick patch which might be considered a proof of concept solution of the issue

1diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
2index 45b0aaa..1dc4d7c 100644
3--- a/intern/cycles/bvh/bvh_build.cpp
4+++ b/intern/cycles/bvh/bvh_build.cpp
5@@ -114,6 +114,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
6 }
7
8 if(bounds.valid()) {
9+ bounds.extend(1e-6f);
10 references.push_back(BVHReference(bounds, j, i, type));
11 root.grow(bounds);
12 center.grow(bounds.center2());
13@@ -146,6 +147,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
14 }
15
16 if(bounds.valid()) {
17+ bounds.extend(1e-6f);
18 int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
19
20 references.push_back(BVHReference(bounds, j, i, packed_type));
21@@ -158,9 +160,11 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
22
23 void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
24 {
25- references.push_back(BVHReference(ob->bounds, -1, i, 0));
26- root.grow(ob->bounds);
27- center.grow(ob->bounds.center2());
28+ BoundBox bounds = ob->bounds;
29+ bounds.extend(1e-6f);
30+ references.push_back(BVHReference(bounds, -1, i, 0));
31+ root.grow(bounds);
32+ center.grow(bounds.center2());
33 }
34
35 static size_t count_curve_segments(Mesh *mesh)
36diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
37index 65f6c9a..68b8637 100644
38--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
39+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
40@@ -142,6 +142,19 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
41 float U = Cx * By - Cy * Bx;
42 float V = Ax * Cy - Ay * Cx;
43 float W = Bx * Ay - By * Ax;
44+
45+ if(U == 0.0f || V == 0.0f || W == 0.0f) {
46+ double CxBy = (double)Cx * (double)By;
47+ double CyBx = (double)Cy * (double)Bx;
48+ U = (float)(CxBy - CyBx);
49+ double AxCy = (double)Ax * (double)Cy;
50+ double AyCx = (double)Ay * (double)Cx;
51+ V = (float)(AxCy - AyCx);
52+ double BxAy = (double)Bx * (double)Ay;
53+ double ByAx = (double)By * (double)Ax;
54+ W = (float)(BxAy - ByAx);
55+ }
56+
57 const int sign_mask = (__float_as_int(U) & 0x80000000);
58 /* TODO(sergey): Check if multiplication plus sign check is faster
59 * or at least same speed (but robust for endian types).
60diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
61index cef5adc..228e571 100644
62--- a/intern/cycles/util/util_boundbox.h
63+++ b/intern/cycles/util/util_boundbox.h
64@@ -176,6 +176,12 @@ public:
65 fabsf(center_diff.y) <= total_size.y &&
66 fabsf(center_diff.z) <= total_size.z;
67 }
68+
69+ __forceinline void extend(float value)
70+ {
71+ min = min - make_float3(value, value, value);
72+ max = max + make_float3(value, value, value);
73+ }
74 };
75
76 __forceinline BoundBox merge(const BoundBox& bbox, const float3& pt)

However, it has two issues still:

a. Consumer GPUs are really slow for double precision arithmetic
b. Extending BVH node boundary might cause some slowdown

But since this never really worked 100% robust it's still considered a TODO. So thanks for the report, but will look into this as a part of general improvement after 2.76 release.