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:29:25 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2016-04-18 23:31:12 +0300
commit71588300d233f795fcf9b0b55ce397b9b81614ff (patch)
treeb7b11180a64838f6dbd571b23a799a9201bac9f3 /intern/cycles/subd
parentc42a796e9ff06d365ae2b41cd122e4bce026bf35 (diff)
Cycles microdisplacement: fix handling of triangles in DiagSplit
Theres still more room for improvement but this makes things useable. Reviewed By: brecht Differential Revision: https://developer.blender.org/D1921
Diffstat (limited to 'intern/cycles/subd')
-rw-r--r--intern/cycles/subd/subd_dice.cpp39
-rw-r--r--intern/cycles/subd/subd_split.cpp134
2 files changed, 88 insertions, 85 deletions
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index 4f27eaf7d1b..a5dfcd21ceb 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -259,17 +259,10 @@ float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv)
void QuadDice::add_corners(SubPatch& sub)
{
/* add verts for patch corners */
- if(sub.patch->is_triangle()) {
- add_vert(sub, 0.0f, 0.0f);
- add_vert(sub, 1.0f, 0.0f);
- add_vert(sub, 0.0f, 1.0f);
- }
- else {
- add_vert(sub, 0.0f, 0.0f);
- add_vert(sub, 1.0f, 0.0f);
- add_vert(sub, 0.0f, 1.0f);
- add_vert(sub, 1.0f, 1.0f);
- }
+ add_vert(sub, 0.0f, 0.0f);
+ add_vert(sub, 1.0f, 0.0f);
+ add_vert(sub, 0.0f, 1.0f);
+ add_vert(sub, 1.0f, 1.0f);
}
void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset)
@@ -458,15 +451,21 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
add_triangle(sub.patch, outer_w[0], outer_u[0], outer_v[0]);
}
else {
- /* center vertex + 6 triangles */
+ /* center vertex + up to 6 triangles */
int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f));
add_triangle(sub.patch, outer_w[0], outer_w[1], center);
- add_triangle(sub.patch, outer_w[1], outer_w[2], center);
+ /* if this is false then there is only one triangle on this side */
+ if(outer_w.size() > 2)
+ add_triangle(sub.patch, outer_w[1], outer_w[2], center);
+
add_triangle(sub.patch, outer_u[0], outer_u[1], center);
- add_triangle(sub.patch, outer_u[1], outer_u[2], center);
+ if(outer_u.size() > 2)
+ add_triangle(sub.patch, outer_u[1], outer_u[2], center);
+
add_triangle(sub.patch, outer_v[0], outer_v[1], center);
- add_triangle(sub.patch, outer_v[1], outer_v[2], center);
+ if(outer_v.size() > 2)
+ add_triangle(sub.patch, outer_v[1], outer_v[2], center);
}
}
@@ -475,6 +474,16 @@ void TriangleDice::dice(SubPatch& sub, EdgeFactors& ef)
/* todo: handle 2 1 1 resolution */
int M = max(ef.tu, max(ef.tv, ef.tw));
+ /* Due to the "slant" of the edges of a triangle compared to a quad, the internal
+ * triangles end up smaller, causing over-tessellation. This is to correct for this
+ * difference in area. Technically its only correct for equilateral triangles, but
+ * its better than how it was.
+ *
+ * (2*cos(radians(30))/3)**0.5
+ */
+ float S = 0.7598356856515927f;
+ M = max((int)ceil(S*M), 1);
+
reserve(ef, M);
add_grid(sub, ef, M);
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 70081673597..05f58cf30f7 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -128,82 +128,62 @@ void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef
assert(ef.tv == T(sub.patch, sub.Pw, sub.Pu));
assert(ef.tw == T(sub.patch, sub.Pu, sub.Pv));
- if(depth == 0) {
- dispatch(sub, ef);
- return;
- }
-
- if(ef.tu == DSPLIT_NON_UNIFORM) {
- /* partition edges */
- TriangleDice::EdgeFactors ef0, ef1;
- float2 Psplit;
-
- partition_edge(sub.patch,
- &Psplit, &ef1.tu, &ef0.tu, sub.Pv, sub.Pw, ef.tu);
-
- /* split */
- int tsplit = T(sub.patch, sub.Pu, Psplit);
- ef0.tv = ef.tv;
- ef0.tw = tsplit;
-
- ef1.tv = tsplit;
- ef1.tw = ef.tw;
+ int non_uniform_count = int(ef.tu == DSPLIT_NON_UNIFORM) +
+ int(ef.tv == DSPLIT_NON_UNIFORM) +
+ int(ef.tw == DSPLIT_NON_UNIFORM);
+
+ switch(non_uniform_count) {
+ case 1: {
+ /* TODO(mai): one edge is non-uniform, split into two triangles */
+ // fallthru
+ }
+ case 2: {
+ /* TODO(mai): two edges are non-uniform, split into triangle and quad */
+ // fallthru
+ }
+ case 3: {
+ /* all three edges are non-uniform, split into three quads */
- /* create subpatches */
- TriangleDice::SubPatch sub0 = {sub.patch, sub.Pu, Psplit, sub.Pw};
- TriangleDice::SubPatch sub1 = {sub.patch, sub.Pu, sub.Pv, Psplit};
+ /* partition edges */
+ QuadDice::EdgeFactors ef0, ef1, ef2;
+ float2 Pu, Pv, Pw, Pcenter;
- split(sub0, ef0, depth+1);
- split(sub1, ef1, depth+1);
- }
- else if(ef.tv == DSPLIT_NON_UNIFORM) {
- /* partition edges */
- TriangleDice::EdgeFactors ef0, ef1;
- float2 Psplit;
+ partition_edge(sub.patch, &Pu, &ef1.tv0, &ef2.tu0, sub.Pw, sub.Pv, ef.tu);
+ partition_edge(sub.patch, &Pv, &ef0.tv0, &ef1.tu0, sub.Pu, sub.Pw, ef.tv);
+ partition_edge(sub.patch, &Pw, &ef2.tv0, &ef0.tu0, sub.Pv, sub.Pu, ef.tw);
+ Pcenter = (Pu + Pv + Pw) * (1.0f / 3.0f);
- partition_edge(sub.patch,
- &Psplit, &ef1.tu, &ef0.tu, sub.Pw, sub.Pu, ef.tv);
+ /* split */
+ int tsplit01 = T(sub.patch, Pv, Pcenter);
+ int tsplit12 = T(sub.patch, Pu, Pcenter);
+ int tsplit20 = T(sub.patch, Pw, Pcenter);
- /* split */
- int tsplit = T(sub.patch, sub.Pv, Psplit);
- ef0.tv = ef.tw;
- ef0.tw = tsplit;
+ ef0.tu1 = tsplit01;
+ ef0.tv1 = tsplit20;
- ef1.tv = tsplit;
- ef1.tw = ef.tu;
+ ef1.tu1 = tsplit12;
+ ef1.tv1 = tsplit01;
- /* create subpatches */
- TriangleDice::SubPatch sub0 = {sub.patch, sub.Pv, Psplit, sub.Pu};
- TriangleDice::SubPatch sub1 = {sub.patch, sub.Pv, sub.Pw, Psplit};
+ ef2.tu1 = tsplit20;
+ ef2.tv1 = tsplit12;
- split(sub0, ef0, depth+1);
- split(sub1, ef1, depth+1);
- }
- else if(ef.tw == DSPLIT_NON_UNIFORM) {
- /* partition edges */
- TriangleDice::EdgeFactors ef0, ef1;
- float2 Psplit;
+ /* create subpatches */
+ QuadDice::SubPatch sub0 = {sub.patch, sub.Pu, Pw, Pv, Pcenter};
+ QuadDice::SubPatch sub1 = {sub.patch, sub.Pw, Pv, Pu, Pcenter};
+ QuadDice::SubPatch sub2 = {sub.patch, sub.Pv, Pu, Pw, Pcenter};
- partition_edge(sub.patch,
- &Psplit, &ef1.tu, &ef0.tu, sub.Pu, sub.Pv, ef.tw);
+ split(sub0, ef0, depth+1);
+ split(sub1, ef1, depth+1);
+ split(sub2, ef2, depth+1);
- /* split */
- int tsplit = T(sub.patch, sub.Pw, Psplit);
- ef0.tv = ef.tu;
- ef0.tw = tsplit;
-
- ef1.tv = tsplit;
- ef1.tw = ef.tv;
-
- /* create subpatches */
- TriangleDice::SubPatch sub0 = {sub.patch, sub.Pw, Psplit, sub.Pv};
- TriangleDice::SubPatch sub1 = {sub.patch, sub.Pw, sub.Pu, Psplit};
-
- split(sub0, ef0, depth+1);
- split(sub1, ef1, depth+1);
+ break;
+ }
+ default: {
+ /* all edges uniform, no splitting needed */
+ dispatch(sub, ef);
+ break;
+ }
}
- else
- dispatch(sub, ef);
}
void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth)
@@ -303,10 +283,6 @@ void DiagSplit::split_triangle(Patch *patch)
TriangleDice::SubPatch& sub = subpatches_triangle[i];
TriangleDice::EdgeFactors& ef = edgefactors_triangle[i];
- ef.tu = 4;
- ef.tv = 4;
- ef.tw = 4;
-
ef.tu = max(ef.tu, 1);
ef.tv = max(ef.tv, 1);
ef.tw = max(ef.tw, 1);
@@ -316,6 +292,24 @@ void DiagSplit::split_triangle(Patch *patch)
subpatches_triangle.clear();
edgefactors_triangle.clear();
+
+ /* triangle might be split into quads so dice quad subpatches as well */
+ QuadDice qdice(params);
+
+ for(size_t i = 0; i < subpatches_quad.size(); i++) {
+ QuadDice::SubPatch& sub = subpatches_quad[i];
+ QuadDice::EdgeFactors& ef = edgefactors_quad[i];
+
+ ef.tu0 = max(ef.tu0, 1);
+ ef.tu1 = max(ef.tu1, 1);
+ ef.tv0 = max(ef.tv0, 1);
+ ef.tv1 = max(ef.tv1, 1);
+
+ qdice.dice(sub, ef);
+ }
+
+ subpatches_quad.clear();
+ edgefactors_quad.clear();
}
void DiagSplit::split_quad(Patch *patch)