diff options
author | Mai Lavelle <mai.lavelle@gmail.com> | 2016-04-18 23:35:49 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2016-04-18 23:47:24 +0300 |
commit | 3068ea34e414e7af6d20af7ab92c69cbd9a33414 (patch) | |
tree | e820479e09c3959219a16e8346c766be3d61f22d /intern/cycles/subd | |
parent | 71588300d233f795fcf9b0b55ce397b9b81614ff (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.h | 2 | ||||
-rw-r--r-- | intern/cycles/subd/subd_split.cpp | 67 |
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); |