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:
-rw-r--r--intern/cycles/blender/addon/properties.py29
-rw-r--r--intern/cycles/blender/addon/ui.py11
-rw-r--r--intern/cycles/blender/blender_curves.cpp10
-rw-r--r--intern/cycles/bvh/bvh.cpp5
-rw-r--r--intern/cycles/kernel/kernel_bvh.h166
-rw-r--r--intern/cycles/kernel/kernel_path.h31
-rw-r--r--intern/cycles/kernel/kernel_shader.h3
-rw-r--r--intern/cycles/kernel/kernel_types.h19
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h5
-rw-r--r--intern/cycles/kernel/svm/svm_types.h2
-rw-r--r--intern/cycles/render/camera.cpp1
-rw-r--r--intern/cycles/render/camera.h1
-rw-r--r--intern/cycles/render/curves.cpp6
-rw-r--r--intern/cycles/render/curves.h5
-rw-r--r--intern/cycles/render/nodes.cpp8
-rw-r--r--intern/cycles/render/session.cpp2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hair_info.c5
17 files changed, 272 insertions, 37 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index ac0a1d7bdb7..b0e0baf4057 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -71,6 +71,7 @@ enum_curve_presets = (
('TRUE_NORMAL', "True Normal", "Use true normals with line segments(good for thin strands)"),
('ACCURATE_PRESET', "Accurate", "Use best line segment settings (suitable for glass materials)"),
('SMOOTH_CURVES', "Smooth Curves", "Use smooth cardinal curves (slowest)"),
+ ('SMOOTH_RIBBONS', "Ribbons", "Use smooth cardinal curves without thickness"),
)
enum_curve_primitives = (
@@ -745,11 +746,23 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
min=0, max=100.0,
default=1.01,
)
+ cls.minimum_width = FloatProperty(
+ name="Minimal width",
+ description="Minimal pixel width for strands (0 - deactivated)",
+ min=0, max=100,
+ default=0.0,
+ )
+ cls.maximum_width = FloatProperty(
+ name="Maximal width",
+ description="Maximum extension that strand radius can be increased by",
+ min=0, max=100,
+ default=0.1,
+ )
cls.subdivisions = IntProperty(
name="Subdivisions",
description="Number of subdivisions used in Cardinal curve intersection (power of 2)",
min=0, max=24,
- default=3,
+ default=4,
)
@classmethod
@@ -765,15 +778,21 @@ class CyclesCurveSettings(bpy.types.PropertyGroup):
description="Cycles hair settings",
type=cls,
)
+ cls.radius_scale = FloatProperty(
+ name="Radius Scaling",
+ description="Multiplier of width properties",
+ min=0.0, max=1000.0,
+ default=0.01,
+ )
cls.root_width = FloatProperty(
- name="Root Size Multiplier",
- description="Multiplier of particle size for the strand's width at root",
+ name="Root Size",
+ description="Strand's width at root",
min=0.0, max=1000.0,
default=1.0,
)
cls.tip_width = FloatProperty(
- name="Tip Size Multiplier",
- description="Multiplier of particle size for the strand's width at tip",
+ name="Tip Multiplier",
+ description="Strand's width at tip",
min=0.0, max=1000.0,
default=0.0,
)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 564a62f257d..92e9c622201 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1079,6 +1079,10 @@ class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
row = layout.row()
row.prop(ccscene, "use_parents", text="Include parents")
+
+ row = layout.row()
+ row.prop(ccscene, "minimum_width", text="Min Pixels")
+ row.prop(ccscene, "maximum_width", text="Max Ext.")
class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
@@ -1103,12 +1107,15 @@ class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
row = layout.row()
row.prop(cpsys, "shape", text="Shape")
- row.prop(cpsys, "use_closetip", text="Close tip")
- layout.label(text="Width multiplier:")
+ layout.label(text="Thickness:")
row = layout.row()
row.prop(cpsys, "root_width", text="Root")
row.prop(cpsys, "tip_width", text="Tip")
+
+ row = layout.row()
+ row.prop(cpsys, "radius_scale", text="Scaling")
+ row.prop(cpsys, "use_closetip", text="Close tip")
class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 768a5a6ee3a..4e0aad8ad14 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -195,7 +195,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
CData->psys_curvenum.push_back(totcurves);
CData->psys_shader.push_back(shader);
- float radius = b_psys.settings().particle_size() * 0.5f;
+ float radius = get_float(cpsys, "radius_scale") * 0.5f;
CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
@@ -884,6 +884,8 @@ void BlenderSync::sync_curve_settings()
CurveSystemManager prev_curve_system_manager = *curve_system_manager;
curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
+ curve_system_manager->minimum_width = get_float(csscene, "minimum_width");
+ curve_system_manager->maximum_width = get_float(csscene, "maximum_width");
if(preset == CURVE_CUSTOM) {
/*custom properties*/
@@ -957,6 +959,12 @@ void BlenderSync::sync_curve_settings()
curve_system_manager->use_backfacing = true;
curve_system_manager->subdivisions = 4;
break;
+ case CURVE_SMOOTH_RIBBONS:
+ /*Cardinal ribbons preset*/
+ curve_system_manager->primitive = CURVE_RIBBONS;
+ curve_system_manager->use_backfacing = false;
+ curve_system_manager->subdivisions = 4;
+ break;
}
}
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index f11b3c4c0bc..5732efef357 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -341,6 +341,9 @@ void BVH::pack_primitives()
int tob = pack.prim_object[i];
Object *ob = objects[tob];
pack.prim_visibility[i] = ob->visibility;
+
+ if(pack.prim_segment[i] != ~0)
+ pack.prim_visibility[i] |= PATH_RAY_CURVE;
}
else {
memset(&pack.tri_woop[i * nsize], 0, sizeof(float4)*3);
@@ -651,6 +654,8 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
float mr = max(mesh->curve_keys[k0].radius,mesh->curve_keys[k1].radius);
bbox.grow(lower, mr);
bbox.grow(upper, mr);
+
+ visibility |= PATH_RAY_CURVE;
}
else {
/* triangles */
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index b44e1194672..8df710052b6 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -113,11 +113,22 @@ __device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, cons
#endif
/* intersect two bounding boxes */
+#ifdef __HAIR__
+__device_inline void bvh_node_intersect(KernelGlobals *kg,
+ bool *traverseChild0, bool *traverseChild1,
+ bool *closestChild1, int *nodeAddr0, int *nodeAddr1,
+ float3 P, float3 idir, float t, uint visibility, int nodeAddr, float difl = 0.0f, float extmax = 0.0f)
+{
+ float hdiff = 1.0f + difl;
+ float ldiff = 1.0f - difl;
+#else
__device_inline void bvh_node_intersect(KernelGlobals *kg,
bool *traverseChild0, bool *traverseChild1,
bool *closestChild1, int *nodeAddr0, int *nodeAddr1,
float3 P, float3 idir, float t, uint visibility, int nodeAddr)
{
+#endif
+
/* fetch node data */
float4 n0xy = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
float4 n1xy = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
@@ -144,6 +155,19 @@ __device_inline void bvh_node_intersect(KernelGlobals *kg,
NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
+#ifdef __HAIR__
+ if(difl != 0.0f) {
+ if(__float_as_int(cnodes.z) & PATH_RAY_CURVE) {
+ c0min = max(ldiff * c0min, c0min - extmax);
+ c0max = min(hdiff * c0max, c0max + extmax);
+ }
+ if(__float_as_int(cnodes.z) & PATH_RAY_CURVE) {
+ c1min = max(ldiff * c1min, c1min - extmax);
+ c1max = min(hdiff * c1max, c1max + extmax);
+ }
+ }
+#endif
+
/* decide which nodes to traverse next */
#ifdef __VISIBILITY_FLAG__
/* this visibility test gives a 5% performance hit, how to solve? */
@@ -257,8 +281,9 @@ __device_inline void curvebounds(float *lower, float *upper, float *extremta, fl
}
__device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
- float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment)
+ float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment, uint *lcg_state = NULL, float difl = 0.0f, float extmax = 0.0f)
{
+ float epsilon = 0.0f;
int depth = kernel_data.curve_kernel_data.subdivisions;
/* curve Intersection check */
@@ -316,21 +341,29 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio
float r_curr = max(r_st, r_en);
+ if((flags & CURVE_KN_RIBBONS) || !(flags & CURVE_KN_BACKFACING))
+ epsilon = 2 * r_curr;
+
/*find bounds - this is slow for cubic curves*/
float upper,lower;
+
+ float zextrem[4];
+ curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z);
+ if(lower - r_curr > isect->t || upper + r_curr < epsilon)
+ return;
+
+ /*minimum width extension*/
+ float mw_extension = min(difl * fabsf(upper), extmax);
+ float r_ext = mw_extension + r_curr;
+
float xextrem[4];
curvebounds(&lower, &upper, &xextrem[0], &xextrem[1], &xextrem[2], &xextrem[3], curve_coef[0].x, curve_coef[1].x, curve_coef[2].x, curve_coef[3].x);
- if(lower > r_curr || upper < -r_curr)
+ if(lower > r_ext || upper < -r_ext)
return;
float yextrem[4];
curvebounds(&lower, &upper, &yextrem[0], &yextrem[1], &yextrem[2], &yextrem[3], curve_coef[0].y, curve_coef[1].y, curve_coef[2].y, curve_coef[3].y);
- if(lower > r_curr || upper < -r_curr)
- return;
-
- float zextrem[4];
- curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z);
- if(lower - r_curr > isect->t || upper + r_curr < 0.0f)
+ if(lower > r_ext || upper < -r_ext)
return;
/*setup recurrent loop*/
@@ -381,7 +414,11 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio
float r2 = r_st + (r_en - r_st) * i_en;
r_curr = max(r1, r2);
- if (bminz - r_curr > isect->t || bmaxz + r_curr < 0.0f|| bminx > r_curr || bmaxx < -r_curr || bminy > r_curr || bmaxy < -r_curr) {
+ mw_extension = min(difl * fabsf(bmaxz), extmax);
+ float r_ext = mw_extension + r_curr;
+ float coverage = 1.0f;
+
+ if (bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) {
/* the bounding box does not overlap the square centered at O.*/
tree += level;
level = tree & -tree;
@@ -426,8 +463,23 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio
level = tree & -tree;
continue;
}
+
+ /* compute coverage */
+ float r_ext = r_curr;
+ coverage = 1.0f;
+ if(difl != 0.0f) {
+ mw_extension = min(difl * fabsf(bmaxz), extmax);
+ r_ext = mw_extension + r_curr;
+ float d = sqrtf(p_curr.x * p_curr.x + p_curr.y * p_curr.y);
+ float d0 = d - r_curr;
+ float d1 = d + r_curr;
+ if (d0 >= 0)
+ coverage = (min(d1 / mw_extension, 1.0f) - min(d0 / mw_extension, 1.0f)) * 0.5;
+ else // inside
+ coverage = (min(d1 / mw_extension, 1.0f) + min(-d0 / mw_extension, 1.0f)) * 0.5;
+ }
- if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_curr * r_curr || p_curr.z <= 0.0f) {
+ if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon) {
tree++;
level = tree & -tree;
continue;
@@ -442,18 +494,28 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio
}
else {
float l = len(p_en - p_st);
+ /*minimum width extension*/
+ float or1 = r1;
+ float or2 = r2;
+ if(difl != 0.0f) {
+ mw_extension = min(len(p_st - P) * difl, extmax);
+ or1 = r1 < mw_extension ? mw_extension : r1;
+ mw_extension = min(len(p_en - P) * difl, extmax);
+ or2 = r2 < mw_extension ? mw_extension : r2;
+ }
+ /* --- */
float3 tg = (p_en - p_st) / l;
- float gd = (r2 - r1) / l;
+ float gd = (or2 - or1) / l;
float difz = -dot(p_st,tg);
float cyla = 1.0f - (tg.z * tg.z * (1 + gd*gd));
- float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + r1)));
+ float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + or1)));
float tcentre = -halfb/cyla;
float zcentre = difz + (tg.z * tcentre);
float3 tdif = - p_st;
tdif.z += tcentre;
float tdifz = dot(tdif,tg);
- float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + r1)));
- float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd;
+ float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + or1)));
+ float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - or1*or1 - 2*or1*tdifz*gd;
float td = tb*tb - 4*cyla*tc;
if (td < 0.0f){
tree++;
@@ -488,10 +550,20 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio
w = clamp((float)w, 0.0f, 1.0f);
/* compute u on the curve segment.*/
- u = i_st * (1 - w) + i_en * w;
+ u = i_st * (1 - w) + i_en * w;
+ r_curr = r1 + (r2 - r1) * w;
+ r_ext = or1 + (or2 - or1) * w;
+ coverage = r_curr/r_ext;
}
/* we found a new intersection.*/
+
+ /*stochastic fade from minimum width*/
+ if(lcg_state && coverage != 1.0f) {
+ if(lcg_step(lcg_state) > coverage)
+ return;
+ }
+
#ifdef __VISIBILITY_FLAG__
/* visibility flag test. we do it here under the assumption
* that most triangles are culled by node flags */
@@ -504,6 +576,7 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio
isect->object = object;
isect->u = u;
isect->v = 0.0f;
+ /*isect->v = 1.0f - coverage; */
isect->t = t;
}
@@ -518,26 +591,38 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio
}
__device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
- float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment)
+ float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment, uint *lcg_state = NULL, float difl = 0.0f, float extmax = 0.0f)
{
/* curve Intersection check */
-
int flags = kernel_data.curve_kernel_data.curveflags;
int prim = kernel_tex_fetch(__prim_index, curveAddr);
float4 v00 = kernel_tex_fetch(__curves, prim);
- int k0 = __float_as_int(v00.x) + segment;
+ int cnum = __float_as_int(v00.x);
+ int k0 = cnum + segment;
int k1 = k0 + 1;
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
float4 P2 = kernel_tex_fetch(__curve_keys, k1);
- float r1 = P1.w;
- float r2 = P2.w;
- float mr = max(r1,r2);
+ float or1 = P1.w;
+ float or2 = P2.w;
float3 p1 = float4_to_float3(P1);
float3 p2 = float4_to_float3(P2);
+
+ /*minimum width extension*/
+ float r1 = or1;
+ float r2 = or2;
+ if(difl != 0.0f) {
+ float pixelsize = min(len(p1 - P) * difl, extmax);
+ r1 = or1 < pixelsize ? pixelsize : or1;
+ pixelsize = min(len(p2 - P) * difl, extmax);
+ r2 = or2 < pixelsize ? pixelsize : or2;
+ }
+ /* --- */
+
+ float mr = max(r1,r2);
float3 dif = P - p1;
float3 dir = 1.0f/idir;
float l = len(p2 - p1);
@@ -558,7 +643,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
float difz = dot(dif,tg);
float a = 1.0f - (dirz*dirz*(1 + gd*gd));
- float halfb = (dot(dir,dif) - dirz*(difz + gd*(difz*gd + r1)));
+ float halfb = dot(dir,dif) - dirz*(difz + gd*(difz*gd + r1));
float tcentre = -halfb/a;
float zcentre = difz + (dirz * tcentre);
@@ -620,6 +705,15 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
z = zcentre + (dirz * correction);
}
+ /*stochastic fade from minimum width*/
+ float adjradius = or1 + z * (or2 - or1) / l;
+ adjradius = adjradius / (r1 + z * gd);
+ if(lcg_state && adjradius != 1.0f) {
+ if(lcg_step(lcg_state) > adjradius)
+ return;
+ }
+ /* --- */
+
if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
if (flags & CURVE_KN_ENCLOSEFILTER) {
@@ -645,6 +739,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
isect->object = object;
isect->u = z/l;
isect->v = td/(4*a*a);
+ /*isect->v = 1.0f - adjradius;*/
isect->t = t;
if(backface)
@@ -655,7 +750,11 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
}
#endif
+#ifdef __HAIR__
+__device bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect, uint *lcg_state = NULL, float difl = 0.0f, float extmax = 0.0f)
+#else
__device bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
+#endif
{
/* traversal stack in CUDA thread-local memory */
int traversalStack[BVH_STACK_SIZE];
@@ -687,9 +786,15 @@ __device bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibi
bool traverseChild0, traverseChild1, closestChild1;
int nodeAddrChild1;
+#ifdef __HAIR__
+ bvh_node_intersect(kg, &traverseChild0, &traverseChild1,
+ &closestChild1, &nodeAddr, &nodeAddrChild1,
+ P, idir, isect->t, visibility, nodeAddr, difl, extmax);
+#else
bvh_node_intersect(kg, &traverseChild0, &traverseChild1,
&closestChild1, &nodeAddr, &nodeAddrChild1,
P, idir, isect->t, visibility, nodeAddr);
+#endif
if(traverseChild0 != traverseChild1) {
/* one child was intersected */
@@ -738,9 +843,9 @@ __device bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibi
uint segment = kernel_tex_fetch(__prim_segment, primAddr);
if(segment != ~0) {
if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_INTERPOLATE)
- bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
+ bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment, lcg_state, difl, extmax);
else
- bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
+ bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment, lcg_state, difl, extmax);
}
else
#endif
@@ -911,13 +1016,22 @@ __device bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, const uint
}
#endif
+#ifdef __HAIR__
+__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect, uint *lcg_state = NULL, float difl = 0.0f, float extmax = 0.0f)
+#else
__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
+#endif
{
#ifdef __OBJECT_MOTION__
if(kernel_data.bvh.have_motion)
return bvh_intersect_motion(kg, ray, visibility, isect);
else
+#ifdef __HAIR__
+ return bvh_intersect(kg, ray, visibility, isect, lcg_state, difl, extmax);
+#else
return bvh_intersect(kg, ray, visibility, isect);
+#endif
+
#else
return bvh_intersect(kg, ray, visibility, isect);
#endif
@@ -1483,6 +1597,10 @@ __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const
sd->dPdv = cross(tg,sd->Ng);
#endif
+ /*add fading parameter for minimum pixel width with transparency bsdf*/
+ /*sd->curve_transparency = isect->v;*/
+ /*sd->curve_radius = sd->u * gd * l + r1;*/
+
if(isect->object != ~0) {
#ifdef __OBJECT_MOTION__
Transform tfm = sd->ob_tfm;
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 7aa1ec365b7..8603b23f19b 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -28,13 +28,13 @@
#include "kernel_curve.h"
#include "kernel_primitive.h"
#include "kernel_projection.h"
+#include "kernel_random.h"
#include "kernel_bvh.h"
#include "kernel_accumulate.h"
#include "kernel_camera.h"
#include "kernel_shader.h"
#include "kernel_light.h"
#include "kernel_emission.h"
-#include "kernel_random.h"
#include "kernel_passes.h"
#ifdef __SUBSURFACE__
@@ -249,7 +249,22 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
/* intersect scene */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
+
+#ifdef __HAIR__
+ float difl = 0.0f;
+ if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
+ float3 pixdiff = ray.dD.dx + ray.dD.dy;
+ /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
+ difl = kernel_data.curve_kernel_data.minimum_width * len(pixdiff) * 0.5f;
+ }
+ float extmax = kernel_data.curve_kernel_data.maximum_width;
+ float rng_hair_seed = path_rng(kg, rng, sample, rng_offset + PRNG_STOCHASTIC_HAIR);
+ uint lcg_state = lcg_init(rng_hair_seed);
+
+ bool hit = scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax);
+#else
bool hit = scene_intersect(kg, &ray, visibility, &isect);
+#endif
#ifdef __LAMP_MIS__
if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) {
@@ -907,7 +922,21 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
+#ifdef __HAIR__
+ float difl = 0.0f;
+ if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
+ float3 pixdiff = ray.dD.dx + ray.dD.dy;
+ /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
+ difl = kernel_data.curve_kernel_data.minimum_width * len(pixdiff) * 0.5f;
+ }
+ float extmax = kernel_data.curve_kernel_data.maximum_width;
+ float rng_hair_seed = path_rng(kg, rng, sample, rng_offset + PRNG_STOCHASTIC_HAIR);
+ uint lcg_state = lcg_init(rng_hair_seed);
+
+ if(!scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax)) {
+#else
if(!scene_intersect(kg, &ray, visibility, &isect)) {
+#endif
/* eval background shader if nothing hit */
if(kernel_data.background.transparent) {
L_transparent += average(throughput);
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 444543bf709..ec532858c8d 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -96,6 +96,9 @@ __device_noinline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#ifdef __HAIR__
sd->segment = ~0;
+ /*elements for minimum hair width using transparency bsdf*/
+ /*sd->curve_transparency = 0.0f;*/
+ /*sd->curve_radius = 0.0f;*/
#endif
#ifdef __UV__
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 526609d0506..82ea6a603fe 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -159,7 +159,8 @@ enum PathTraceDimension {
PRNG_LIGHT_V = 5,
PRNG_LIGHT_F = 6,
PRNG_TERMINATE = 7,
- PRNG_BOUNCE_NUM = 8
+ PRNG_BOUNCE_NUM = 8,
+ PRNG_STOCHASTIC_HAIR = 9
};
/* these flags values correspond to raytypes in osl.cpp, so keep them in sync!
@@ -184,6 +185,9 @@ enum PathRayFlag {
PATH_RAY_ALL = (1|2|4|8|16|32|64|128|256|512),
+ /* visibility flag to define curve segments*/
+ PATH_RAY_CURVE = 1024,
+
/* this gives collisions with localview bits
* see: CYCLES_LOCAL_LAYER_HACK(), grr - Campbell */
PATH_RAY_LAYER_SHIFT = (32-20)
@@ -486,6 +490,9 @@ typedef struct ShaderData {
#ifdef __HAIR__
/* for curves, segment number in curve, ~0 for triangles */
int segment;
+ /* variables for minimum hair width using transparency bsdf */
+ /*float curve_transparency; */
+ /*float curve_radius; */
#endif
/* parametric coordinates
* - barycentric weights for triangles */
@@ -575,6 +582,10 @@ typedef struct KernelCamera {
/* render size */
float width, height;
+ int resolution;
+ int pad1;
+ int pad2;
+ int pad3;
/* more matrices */
Transform screentoworld;
@@ -727,6 +738,12 @@ typedef struct KernelCurves {
float encasing_ratio;
int curveflags;
int subdivisions;
+
+ float minimum_width;
+ float maximum_width;
+ float curve_epsilon;
+ int pad1;
+
} KernelCurves;
typedef struct KernelBSSRDF {
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index a04f4ea0fa7..a9e69c8e405 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -166,6 +166,11 @@ __device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack
stack_store_float(stack, out_offset, data);
break;
}
+ /*case NODE_INFO_CURVE_FADE: {
+ data = sd->curve_transparency;
+ stack_store_float(stack, out_offset, data);
+ break;
+ }*/
case NODE_INFO_CURVE_TANGENT_NORMAL: {
data3 = curve_tangent_normal(kg, sd);
stack_store_float3(stack, out_offset, data3);
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 70d73f98498..d89fde898dc 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -137,6 +137,8 @@ typedef enum NodeHairInfo {
NODE_INFO_CURVE_IS_STRAND,
NODE_INFO_CURVE_INTERCEPT,
NODE_INFO_CURVE_THICKNESS,
+ /*fade for minimum hair width transpency*/
+ /*NODE_INFO_CURVE_FADE,*/
NODE_INFO_CURVE_TANGENT_NORMAL
} NodeHairInfo;
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 3ca19496b72..c88b0f3dfbc 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -236,6 +236,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
/* render size */
kcam->width = width;
kcam->height = height;
+ kcam->resolution = resolution;
/* store differentials */
kcam->dx = float3_to_float4(dx);
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 197a4da588c..fa4a9487af0 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -66,6 +66,7 @@ public:
/* screen */
int width, height;
+ int resolution;
BoundBox2D viewplane;
/* border */
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
index 9fa867ae723..3fcd78b0152 100644
--- a/intern/cycles/render/curves.cpp
+++ b/intern/cycles/render/curves.cpp
@@ -89,6 +89,8 @@ CurveSystemManager::CurveSystemManager()
normalmix = 1.0f;
encasing_ratio = 1.01f;
+ minimum_width = 0.0f;
+ maximum_width = 0.0f;
use_curves = true;
use_smooth = true;
@@ -149,6 +151,8 @@ void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scen
kcurve->normalmix = normalmix;
kcurve->encasing_ratio = encasing_ratio;
+ kcurve->minimum_width = minimum_width;
+ kcurve->maximum_width = maximum_width;
kcurve->subdivisions = subdivisions;
}
@@ -172,6 +176,8 @@ bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager)
use_tangent_normal_correction == CurveSystemManager.use_tangent_normal_correction &&
use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
encasing_ratio == CurveSystemManager.encasing_ratio &&
+ minimum_width == CurveSystemManager.minimum_width &&
+ maximum_width == CurveSystemManager.maximum_width &&
use_backfacing == CurveSystemManager.use_backfacing &&
normalmix == CurveSystemManager.normalmix &&
use_smooth == CurveSystemManager.use_smooth &&
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 3527998339c..42f0498617e 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -37,7 +37,8 @@ typedef enum curve_presets {
CURVE_TANGENT_SHADING,
CURVE_TRUE_NORMAL,
CURVE_ACCURATE_PRESET,
- CURVE_SMOOTH_CURVES
+ CURVE_SMOOTH_CURVES,
+ CURVE_SMOOTH_RIBBONS
} curve_presets;
typedef enum curve_primitives {
@@ -107,6 +108,8 @@ public:
float normalmix;
float encasing_ratio;
+ float minimum_width;
+ float maximum_width;
bool use_curves;
bool use_smooth;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index b4ff6e3152b..083b79e8aaf 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -2281,6 +2281,8 @@ HairInfoNode::HairInfoNode()
add_output("Intercept", SHADER_SOCKET_FLOAT);
add_output("Thickness", SHADER_SOCKET_FLOAT);
add_output("Tangent Normal", SHADER_SOCKET_NORMAL);
+ /*output for minimum hair width transparency - deactivated*/
+ /*add_output("Fade", SHADER_SOCKET_FLOAT);*/
}
void HairInfoNode::attributes(AttributeRequestSet *attributes)
@@ -2322,6 +2324,12 @@ void HairInfoNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, out->stack_offset);
}
+ /*out = output("Fade");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, out->stack_offset);
+ }*/
+
}
void HairInfoNode::compile(OSLCompiler& compiler)
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 075f5eb6bab..569c29e0b09 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -719,10 +719,12 @@ void Session::update_scene()
Camera *cam = scene->camera;
int width = tile_manager.state.buffer.full_width;
int height = tile_manager.state.buffer.full_height;
+ int resolution = tile_manager.state.resolution_divider;
if(width != cam->width || height != cam->height) {
cam->width = width;
cam->height = height;
+ cam->resolution = resolution;
cam->tag_update();
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
index 86c31086190..577ac619422 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hair_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
@@ -28,10 +28,11 @@
#include "../node_shader_util.h"
static bNodeSocketTemplate outputs[] = {
- { SOCK_FLOAT, 0, N_("Is Strand"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Is Strand"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Intercept"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("Tangent Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ /*{ SOCK_FLOAT, 0, N_("Fade"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},*/
{ -1, 0, "" }
};