[Bf-blender-cvs] [c1a27a7] master: Cycles microdisplacement: preserve smooth normals for linear subdivison

Mai Lavelle noreply at git.blender.org
Wed Apr 13 01:38:28 CEST 2016


Commit: c1a27a76cf9f40ab9dabb5888ee535e585444fcd
Author: Mai Lavelle
Date:   Wed Apr 13 01:17:34 2016 +0200
Branches: master
https://developer.blender.org/rBc1a27a76cf9f40ab9dabb5888ee535e585444fcd

Cycles microdisplacement: preserve smooth normals for linear subdivison

This way we prevent cracks in the model due to discontinuous normals, by using
smooth normals for displacement instead of always getting flat normals after
linear subdivision.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D1916

===================================================================

M	intern/cycles/render/mesh.cpp
M	intern/cycles/subd/subd_dice.cpp
M	intern/cycles/subd/subd_patch.cpp
M	intern/cycles/subd/subd_patch.h
M	intern/cycles/subd/subd_split.cpp

===================================================================

diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index aa9f773..241a1c4 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1451,31 +1451,63 @@ void Mesh::tessellate(DiagSplit *split)
 {
 	int num_faces = triangles.size();
 
+	add_face_normals();
+	add_vertex_normals();
+
+	Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
+	float3 *fN = attr_fN->data_float3();
+
+	Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
+	float3 *vN = attr_vN->data_float3();
+
 	for(int f = 0; f < num_faces; f++) {
 		if(!forms_quad[f]) {
 			/* triangle */
-			LinearTrianglePatch* patch = new LinearTrianglePatch();
-			float3 *hull = patch->hull;
+			LinearTrianglePatch patch;
+			float3 *hull = patch.hull;
+			float3 *normals = patch.normals;
 
 			for(int i = 0; i < 3; i++) {
 				hull[i] = verts[triangles[f].v[i]];
 			}
 
-			split->split_triangle(patch);
-			delete patch;
+			if(smooth[f]) {
+				for(int i = 0; i < 3; i++) {
+					normals[i] = vN[triangles[f].v[i]];
+				}
+			}
+			else {
+				for(int i = 0; i < 3; i++) {
+					normals[i] = fN[f];
+				}
+			}
+
+			split->split_triangle(&patch);
 		}
 		else {
 			/* quad */
-			LinearQuadPatch* patch = new LinearQuadPatch();
-			float3 *hull = patch->hull;
+			LinearQuadPatch patch;
+			float3 *hull = patch.hull;
+			float3 *normals = patch.normals;
 
 			hull[0] = verts[triangles[f  ].v[0]];
 			hull[1] = verts[triangles[f  ].v[1]];
 			hull[3] = verts[triangles[f  ].v[2]];
 			hull[2] = verts[triangles[f+1].v[2]];
 
-			split->split_quad(patch);
-			delete patch;
+			if(smooth[f]) {
+				normals[0] = vN[triangles[f  ].v[0]];
+				normals[1] = vN[triangles[f  ].v[1]];
+				normals[3] = vN[triangles[f  ].v[2]];
+				normals[2] = vN[triangles[f+1].v[2]];
+			}
+			else {
+				for(int i = 0; i < 4; i++) {
+					normals[i] = fN[f];
+				}
+			}
+
+			split->split_quad(&patch);
 
 			// consume second triangle in quad
 			f++;
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index 301f30c..4f27eaf 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -58,10 +58,9 @@ void EdgeDice::reserve(int num_verts, int num_tris)
 
 int EdgeDice::add_vert(Patch *patch, float2 uv)
 {
-	float3 P, N, dPdu, dPdv;
+	float3 P, N;
 
-	patch->eval(&P, &dPdu, &dPdv, uv.x, uv.y);
-	N = normalize(cross(dPdu, dPdv));
+	patch->eval(&P, NULL, NULL, &N, uv.x, uv.y);
 
 	assert(vert_offset < params.mesh->verts.size());
 
@@ -81,7 +80,7 @@ int EdgeDice::add_vert(Patch *patch, float2 uv)
 
 void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
 {
-	params.mesh->add_triangle(v0, v1, v2, params.shader, params.smooth);
+	params.mesh->add_triangle(v0, v1, v2, params.shader, params.smooth, false);
 
 	if(params.ptex) {
 		Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
@@ -159,7 +158,7 @@ float3 QuadDice::eval_projected(SubPatch& sub, float u, float v)
 	float2 uv = map_uv(sub, u, v);
 	float3 P;
 
-	sub.patch->eval(&P, NULL, NULL, uv.x, uv.y);
+	sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
 	if(params.camera)
 		P = transform_perspective(&params.camera->worldtoraster, P);
 
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index 0db46ec..3b0fb5b 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -57,7 +57,7 @@ static void decasteljau_bicubic(float3 *P, float3 *du, float3 *dv, const float3
 
 /* Linear Quad Patch */
 
-void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
+void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
 {
 	float3 d0 = interp(hull[0], hull[1], u);
 	float3 d1 = interp(hull[2], hull[3], u);
@@ -68,6 +68,10 @@ void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float
 		*dPdu = interp(hull[1] - hull[0], hull[3] - hull[2], v);
 		*dPdv = interp(hull[2] - hull[0], hull[3] - hull[1], u);
 	}
+
+	if(N) {
+		*N = normalize(interp(interp(normals[0], normals[1], u), interp(normals[2], normals[3], u), v));
+	}
 }
 
 BoundBox LinearQuadPatch::bound()
@@ -82,7 +86,7 @@ BoundBox LinearQuadPatch::bound()
 
 /* Linear Triangle Patch */
 
-void LinearTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
+void LinearTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
 {
 	*P = u*hull[0] + v*hull[1] + (1.0f - u - v)*hull[2];
 
@@ -90,6 +94,10 @@ void LinearTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, f
 		*dPdu = hull[0] - hull[2];
 		*dPdv = hull[1] - hull[2];
 	}
+
+	if(N) {
+		*N = normalize(u*normals[0] + v*normals[1] + (1.0f - u - v)*normals[2]);
+	}
 }
 
 BoundBox LinearTrianglePatch::bound()
@@ -104,9 +112,22 @@ BoundBox LinearTrianglePatch::bound()
 
 /* Bicubic Patch */
 
-void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
+void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
 {
-	decasteljau_bicubic(P, dPdu, dPdv, hull, u, v);
+	if (N) {
+		float3 dPdu_, dPdv_;
+		decasteljau_bicubic(P, &dPdu_, &dPdv_, hull, u, v);
+
+		if (dPdu && dPdv) {
+			*dPdu = dPdu_;
+			*dPdv = dPdv_;
+		}
+
+		*N = normalize(cross(dPdu_, dPdv_));
+	}
+	else {
+		decasteljau_bicubic(P, dPdu, dPdv, hull, u, v);
+	}
 }
 
 BoundBox BicubicPatch::bound()
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 9be4606..bfa0441 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -25,7 +25,7 @@ CCL_NAMESPACE_BEGIN
 class Patch {
 public:
 	virtual ~Patch() {}
-	virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v) = 0;
+	virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) = 0;
 	virtual bool is_triangle() { return false; }
 	virtual BoundBox bound() = 0;
 	virtual int ptex_face_id() { return -1; }
@@ -36,8 +36,9 @@ public:
 class LinearQuadPatch : public Patch {
 public:
 	float3 hull[4];
+	float3 normals[4];
 
-	void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
+	void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
 	bool is_triangle() { return false; }
 	BoundBox bound();
 };
@@ -47,8 +48,9 @@ public:
 class LinearTrianglePatch : public Patch {
 public:
 	float3 hull[3];
+	float3 normals[3];
 
-	void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
+	void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
 	bool is_triangle() { return true; }
 	BoundBox bound();
 };
@@ -59,7 +61,7 @@ class BicubicPatch : public Patch {
 public:
 	float3 hull[16];
 
-	void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
+	void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
 	bool is_triangle() { return false; }
 	BoundBox bound();
 };
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 095eefe..7008167 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -50,7 +50,7 @@ float3 DiagSplit::to_world(Patch *patch, float2 uv)
 {
 	float3 P;
 
-	patch->eval(&P, NULL, NULL, uv.x, uv.y);
+	patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
 	if(params.camera)
 		P = transform_point(&params.objecttoworld, P);




More information about the Bf-blender-cvs mailing list