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:
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/attribute.cpp5
-rw-r--r--intern/cycles/render/geometry.cpp59
-rw-r--r--intern/cycles/render/hair.cpp115
-rw-r--r--intern/cycles/render/hair.h4
4 files changed, 163 insertions, 20 deletions
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index aaf21ad9fd2..d7e6939cd80 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -366,6 +366,8 @@ const char *Attribute::standard_name(AttributeStandard std)
return "pointiness";
case ATTR_STD_RANDOM_PER_ISLAND:
return "random_per_island";
+ case ATTR_STD_SHADOW_TRANSPARENCY:
+ return "shadow_transparency";
case ATTR_STD_NOT_FOUND:
case ATTR_STD_NONE:
case ATTR_STD_NUM:
@@ -603,6 +605,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_RANDOM_PER_ISLAND:
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
break;
+ case ATTR_STD_SHADOW_TRANSPARENCY:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
+ break;
default:
assert(0);
break;
diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp
index 5d89060c1a1..5cedab24ceb 100644
--- a/intern/cycles/render/geometry.cpp
+++ b/intern/cycles/render/geometry.cpp
@@ -734,6 +734,10 @@ void GeometryManager::device_update_attributes(Device *device,
Shader *shader = static_cast<Shader *>(node);
geom_attributes[i].add(shader->attributes);
}
+
+ if (geom->is_hair() && static_cast<Hair *>(geom)->need_shadow_transparency()) {
+ geom_attributes[i].add(ATTR_STD_SHADOW_TRANSPARENCY);
+ }
}
/* convert object attributes to use the same data structures as geometry ones */
@@ -1659,6 +1663,7 @@ void GeometryManager::device_update(Device *device,
VLOG(1) << "Total " << scene->geometry.size() << " meshes.";
bool true_displacement_used = false;
+ bool curve_shadow_transparency_used = false;
size_t total_tess_needed = 0;
{
@@ -1669,26 +1674,33 @@ void GeometryManager::device_update(Device *device,
});
foreach (Geometry *geom, scene->geometry) {
- if (geom->is_modified() &&
- (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) {
- Mesh *mesh = static_cast<Mesh *>(geom);
+ if (geom->is_modified()) {
+ if ((geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
- /* Update normals. */
- mesh->add_face_normals();
- mesh->add_vertex_normals();
+ /* Update normals. */
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
- if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
- mesh->add_undisplaced();
- }
+ if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
+ mesh->add_undisplaced();
+ }
- /* Test if we need tessellation. */
- if (mesh->need_tesselation()) {
- total_tess_needed++;
- }
+ /* Test if we need tessellation. */
+ if (mesh->need_tesselation()) {
+ total_tess_needed++;
+ }
- /* Test if we need displacement. */
- if (mesh->has_true_displacement()) {
- true_displacement_used = true;
+ /* Test if we need displacement. */
+ if (mesh->has_true_displacement()) {
+ true_displacement_used = true;
+ }
+ }
+ else if (geom->geometry_type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ if (hair->need_shadow_transparency()) {
+ curve_shadow_transparency_used = true;
+ }
}
if (progress.get_cancel()) {
@@ -1752,7 +1764,7 @@ void GeometryManager::device_update(Device *device,
/* Update images needed for true displacement. */
bool old_need_object_flags_update = false;
- if (true_displacement_used) {
+ if (true_displacement_used || curve_shadow_transparency_used) {
scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) {
scene->update_stats->geometry.times.add_entry(
@@ -1770,7 +1782,7 @@ void GeometryManager::device_update(Device *device,
const BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
device->get_bvh_layout_mask());
mesh_calc_offset(scene, bvh_layout);
- if (true_displacement_used) {
+ if (true_displacement_used || curve_shadow_transparency_used) {
scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) {
scene->update_stats->geometry.times.add_entry(
@@ -1795,8 +1807,9 @@ void GeometryManager::device_update(Device *device,
}
}
- /* Update displacement. */
+ /* Update displacement and hair shadow transparency. */
bool displacement_done = false;
+ bool curve_shadow_transparency_done = false;
size_t num_bvh = 0;
{
@@ -1817,6 +1830,12 @@ void GeometryManager::device_update(Device *device,
displacement_done = true;
}
}
+ else if (geom->geometry_type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ if (hair->update_shadow_transparency(device, scene, progress)) {
+ curve_shadow_transparency_done = true;
+ }
+ }
}
if (geom->is_modified() || geom->need_update_bvh_for_offset) {
@@ -1836,7 +1855,7 @@ void GeometryManager::device_update(Device *device,
}
/* Device re-update after displacement. */
- if (displacement_done) {
+ if (displacement_done || curve_shadow_transparency_done) {
scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) {
scene->update_stats->geometry.times.add_entry(
diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp
index e757e3fd3e0..4656148119a 100644
--- a/intern/cycles/render/hair.cpp
+++ b/intern/cycles/render/hair.cpp
@@ -18,8 +18,13 @@
#include "render/curves.h"
#include "render/hair.h"
+#include "render/object.h"
#include "render/scene.h"
+#include "integrator/shader_eval.h"
+
+#include "util/util_progress.h"
+
CCL_NAMESPACE_BEGIN
/* Hair Curve */
@@ -514,4 +519,114 @@ PrimitiveType Hair::primitive_type() const
((curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK);
}
+/* Fill in coordinates for curve transparency shader evaluation on device. */
+static int fill_shader_input(const Hair *hair,
+ const int object_index,
+ device_vector<KernelShaderEvalInput> &d_input)
+{
+ int d_input_size = 0;
+ KernelShaderEvalInput *d_input_data = d_input.data();
+
+ const int num_curves = hair->num_curves();
+ for (int i = 0; i < num_curves; i++) {
+ const Hair::Curve curve = hair->get_curve(i);
+ const int num_segments = curve.num_segments();
+
+ for (int j = 0; j < num_segments + 1; j++) {
+ KernelShaderEvalInput in;
+ in.object = object_index;
+ in.prim = hair->prim_offset + i;
+ in.u = (j < num_segments) ? 0.0f : 1.0f;
+ in.v = (j < num_segments) ? __int_as_float(j) : __int_as_float(j - 1);
+ d_input_data[d_input_size++] = in;
+ }
+ }
+
+ return d_input_size;
+}
+
+/* Read back curve transparency shader output. */
+static void read_shader_output(float *shadow_transparency,
+ bool &is_fully_opaque,
+ const device_vector<float> &d_output)
+{
+ const int num_keys = d_output.size();
+ const float *output_data = d_output.data();
+ bool is_opaque = true;
+
+ for (int i = 0; i < num_keys; i++) {
+ shadow_transparency[i] = output_data[i];
+ if (shadow_transparency[i] > 0.0f) {
+ is_opaque = false;
+ }
+ }
+
+ is_fully_opaque = is_opaque;
+}
+
+bool Hair::need_shadow_transparency()
+{
+ for (const Node *node : used_shaders) {
+ const Shader *shader = static_cast<const Shader *>(node);
+ if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Hair::update_shadow_transparency(Device *device, Scene *scene, Progress &progress)
+{
+ if (!need_shadow_transparency()) {
+ /* If no shaders with shadow transparency, remove attribute. */
+ Attribute *attr = attributes.find(ATTR_STD_SHADOW_TRANSPARENCY);
+ if (attr) {
+ attributes.remove(attr);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ string msg = string_printf("Computing Shadow Transparency %s", name.c_str());
+ progress.set_status("Updating Hair", msg);
+
+ /* Create shadow transparency attribute. */
+ Attribute *attr = attributes.find(ATTR_STD_SHADOW_TRANSPARENCY);
+ const bool attribute_exists = (attr != nullptr);
+ if (!attribute_exists) {
+ attr = attributes.add(ATTR_STD_SHADOW_TRANSPARENCY);
+ }
+
+ float *attr_data = attr->data_float();
+
+ /* Find object index. */
+ size_t object_index = OBJECT_NONE;
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ if (scene->objects[i]->get_geometry() == this) {
+ object_index = i;
+ break;
+ }
+ }
+
+ /* Evaluate shader on device. */
+ ShaderEval shader_eval(device, progress);
+ bool is_fully_opaque = false;
+ shader_eval.eval(SHADER_EVAL_CURVE_SHADOW_TRANSPARENCY,
+ num_keys(),
+ 1,
+ function_bind(&fill_shader_input, this, object_index, _1),
+ function_bind(&read_shader_output, attr_data, is_fully_opaque, _1));
+
+ if (is_fully_opaque) {
+ attributes.remove(attr);
+ return attribute_exists;
+ }
+
+ return true;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h
index 920e9601b35..3e91fc3dcbb 100644
--- a/intern/cycles/render/hair.h
+++ b/intern/cycles/render/hair.h
@@ -153,6 +153,10 @@ class Hair : public Geometry {
KernelCurveSegment *curve_segments);
PrimitiveType primitive_type() const override;
+
+ /* Attributes */
+ bool need_shadow_transparency();
+ bool update_shadow_transparency(Device *device, Scene *scene, Progress &progress);
};
CCL_NAMESPACE_END