Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMai Lavelle <mai.lavelle@gmail.com>2016-04-18 23:35:49 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2016-04-18 23:47:24 +0300
commit3068ea34e414e7af6d20af7ab92c69cbd9a33414 (patch)
treee820479e09c3959219a16e8346c766be3d61f22d /intern/cycles/subd
parent71588300d233f795fcf9b0b55ce397b9b81614ff (diff)
Cycles microdisplacement: add max subdivision setting
This is to prevent situations such as when the camera gets very close to a mesh and causes it to be tessellated into an excessive amount of micropolygons. In REYES this is known as the eye-splits problem. Reviewed By: brecht Differential Revision: https://developer.blender.org/D1922
Diffstat (limited to 'intern/cycles/subd')
-rw-r--r--intern/cycles/subd/subd_dice.h2
-rw-r--r--intern/cycles/subd/subd_split.cpp67
2 files changed, 69 insertions, 0 deletions
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 2b11e4b0bf5..8450a43129e 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -40,6 +40,7 @@ struct SubdParams {
int test_steps;
int split_threshold;
float dicing_rate;
+ int max_level;
Camera *camera;
Transform objecttoworld;
@@ -53,6 +54,7 @@ struct SubdParams {
test_steps = 3;
split_threshold = 1;
dicing_rate = 0.1f;
+ max_level = 12;
camera = NULL;
}
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 05f58cf30f7..c4af8cc8c43 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -112,6 +112,59 @@ void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2
}
}
+static float2 right_to_equilateral(float2 P)
+{
+ static const float2 A = make_float2(1.0f, 0.5f);
+ static const float2 B = make_float2(0.0f, sinf(M_PI_F/3.0f));
+ return make_float2(dot(P, A), dot(P, B));
+}
+
+static void limit_edge_factors(const TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int max_t)
+{
+ float2 Pu = sub.Pu;
+ float2 Pv = sub.Pv;
+ float2 Pw = sub.Pw;
+
+ if(sub.patch->is_triangle()) {
+ Pu = right_to_equilateral(Pu);
+ Pv = right_to_equilateral(Pv);
+ Pw = right_to_equilateral(Pw);
+ }
+
+ int tu = int(max_t * len(Pw - Pv));
+ int tv = int(max_t * len(Pw - Pu));
+ int tw = int(max_t * len(Pv - Pu));
+
+ ef.tu = tu <= 1 ? 1 : min(ef.tu, tu);
+ ef.tv = tv <= 1 ? 1 : min(ef.tv, tv);
+ ef.tw = tw <= 1 ? 1 : min(ef.tw, tw);
+}
+
+static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int max_t)
+{
+ float2 P00 = sub.P00;
+ float2 P01 = sub.P01;
+ float2 P10 = sub.P10;
+ float2 P11 = sub.P11;
+
+ if(sub.patch->is_triangle()) {
+ P00 = right_to_equilateral(P00);
+ P01 = right_to_equilateral(P01);
+ P10 = right_to_equilateral(P10);
+ P11 = right_to_equilateral(P11);
+ }
+
+ int tu0 = int(max_t * len(P10 - P00));
+ int tu1 = int(max_t * len(P11 - P01));
+ int tv0 = int(max_t * len(P01 - P00));
+ int tv1 = int(max_t * len(P11 - P10));
+
+ ef.tu0 = tu0 <= 1 ? 1 : min(ef.tu0, tu0);
+ ef.tu1 = tu1 <= 1 ? 1 : min(ef.tu1, tu1);
+ ef.tv0 = tv0 <= 1 ? 1 : min(ef.tv0, tv0);
+ ef.tv1 = tv1 <= 1 ? 1 : min(ef.tv1, tv1);
+}
+
void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth)
{
if(depth > 32) {
@@ -172,6 +225,10 @@ void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef
QuadDice::SubPatch sub1 = {sub.patch, sub.Pw, Pv, Pu, Pcenter};
QuadDice::SubPatch sub2 = {sub.patch, sub.Pv, Pu, Pw, Pcenter};
+ limit_edge_factors(sub0, ef0, 1 << params.max_level);
+ limit_edge_factors(sub1, ef1, 1 << params.max_level);
+ limit_edge_factors(sub2, ef2, 1 << params.max_level);
+
split(sub0, ef0, depth+1);
split(sub1, ef1, depth+1);
split(sub2, ef2, depth+1);
@@ -228,6 +285,9 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
QuadDice::SubPatch sub0 = {sub.patch, sub.P00, Pu0, sub.P01, Pu1};
QuadDice::SubPatch sub1 = {sub.patch, Pu0, sub.P10, Pu1, sub.P11};
+ limit_edge_factors(sub0, ef0, 1 << params.max_level);
+ limit_edge_factors(sub1, ef1, 1 << params.max_level);
+
split(sub0, ef0, depth+1);
split(sub1, ef1, depth+1);
}
@@ -253,6 +313,9 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
QuadDice::SubPatch sub0 = {sub.patch, sub.P00, sub.P10, Pv0, Pv1};
QuadDice::SubPatch sub1 = {sub.patch, Pv0, Pv1, sub.P01, sub.P11};
+ limit_edge_factors(sub0, ef0, 1 << params.max_level);
+ limit_edge_factors(sub1, ef1, 1 << params.max_level);
+
split(sub0, ef0, depth+1);
split(sub1, ef1, depth+1);
}
@@ -275,6 +338,8 @@ void DiagSplit::split_triangle(Patch *patch)
ef_split.tv = T(patch, sub_split.Pw, sub_split.Pu);
ef_split.tw = T(patch, sub_split.Pu, sub_split.Pv);
+ limit_edge_factors(sub_split, ef_split, 1 << params.max_level);
+
split(sub_split, ef_split);
TriangleDice dice(params);
@@ -328,6 +393,8 @@ void DiagSplit::split_quad(Patch *patch)
ef_split.tv0 = T(patch, sub_split.P00, sub_split.P01);
ef_split.tv1 = T(patch, sub_split.P10, sub_split.P11);
+ limit_edge_factors(sub_split, ef_split, 1 << params.max_level);
+
split(sub_split, ef_split);
QuadDice dice(params);