diff options
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 29 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 11 | ||||
-rw-r--r-- | intern/cycles/blender/blender_curves.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_bvh.h | 166 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 31 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_shader.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 19 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_geometry.h | 5 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/camera.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/curves.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/render/curves.h | 5 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/render/session.cpp | 2 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_hair_info.c | 5 |
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, "" } }; |