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/mesh_displace.cpp')
-rw-r--r--intern/cycles/render/mesh_displace.cpp571
1 files changed, 288 insertions, 283 deletions
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 53b9bfa3451..5ae9348d83e 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -26,296 +26,301 @@
CCL_NAMESPACE_BEGIN
-static float3 compute_face_normal(const Mesh::Triangle& t, float3 *verts)
+static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
{
- float3 v0 = verts[t.v[0]];
- float3 v1 = verts[t.v[1]];
- float3 v2 = verts[t.v[2]];
+ float3 v0 = verts[t.v[0]];
+ float3 v1 = verts[t.v[1]];
+ float3 v2 = verts[t.v[2]];
- float3 norm = cross(v1 - v0, v2 - v0);
- float normlen = len(norm);
+ float3 norm = cross(v1 - v0, v2 - v0);
+ float normlen = len(norm);
- if(normlen == 0.0f)
- return make_float3(1.0f, 0.0f, 0.0f);
+ if (normlen == 0.0f)
+ return make_float3(1.0f, 0.0f, 0.0f);
- return norm / normlen;
+ return norm / normlen;
}
-bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress)
+bool MeshManager::displace(
+ Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress)
{
- /* verify if we have a displacement shader */
- if(!mesh->has_true_displacement()) {
- return false;
- }
-
- string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
- progress.set_status("Updating Mesh", msg);
-
- /* find object index. todo: is arbitrary */
- size_t object_index = OBJECT_NONE;
-
- for(size_t i = 0; i < scene->objects.size(); i++) {
- if(scene->objects[i]->mesh == mesh) {
- object_index = i;
- break;
- }
- }
-
- /* setup input for device task */
- const size_t num_verts = mesh->verts.size();
- vector<bool> done(num_verts, false);
- device_vector<uint4> d_input(device, "displace_input", MEM_READ_ONLY);
- uint4 *d_input_data = d_input.alloc(num_verts);
- size_t d_input_size = 0;
-
- size_t num_triangles = mesh->num_triangles();
- for(size_t i = 0; i < num_triangles; i++) {
- Mesh::Triangle t = mesh->get_triangle(i);
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
-
- for(int j = 0; j < 3; j++) {
- if(done[t.v[j]])
- continue;
-
- done[t.v[j]] = true;
-
- /* set up object, primitive and barycentric coordinates */
- int object = object_index;
- int prim = mesh->tri_offset + i;
- float u, v;
-
- switch(j) {
- case 0:
- u = 1.0f;
- v = 0.0f;
- break;
- case 1:
- u = 0.0f;
- v = 1.0f;
- break;
- default:
- u = 0.0f;
- v = 0.0f;
- break;
- }
-
- /* back */
- uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
- d_input_data[d_input_size++] = in;
- }
- }
-
- if(d_input_size == 0)
- return false;
-
- /* run device task */
- device_vector<float4> d_output(device, "displace_output", MEM_READ_WRITE);
- d_output.alloc(d_input_size);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- /* needs to be up to data for attribute access */
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- DeviceTask task(DeviceTask::SHADER);
- task.shader_input = d_input.device_pointer;
- task.shader_output = d_output.device_pointer;
- task.shader_eval_type = SHADER_EVAL_DISPLACE;
- task.shader_x = 0;
- task.shader_w = d_output.size();
- task.num_samples = 1;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
-
- device->task_add(task);
- device->task_wait();
-
- if(progress.get_cancel()) {
- d_input.free();
- d_output.free();
- return false;
- }
-
- d_output.copy_from_device(0, 1, d_output.size());
- d_input.free();
-
- /* read result */
- done.clear();
- done.resize(num_verts, false);
- int k = 0;
-
- float4 *offset = d_output.data();
-
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(size_t i = 0; i < num_triangles; i++) {
- Mesh::Triangle t = mesh->get_triangle(i);
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
-
- for(int j = 0; j < 3; j++) {
- if(!done[t.v[j]]) {
- done[t.v[j]] = true;
- float3 off = float4_to_float3(offset[k++]);
- /* Avoid illegal vertex coordinates. */
- off = ensure_finite3(off);
- mesh->verts[t.v[j]] += off;
- if(attr_mP != NULL) {
- for(int step = 0; step < mesh->motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*num_verts;
- mP[t.v[j]] += off;
- }
- }
- }
- }
- }
-
- d_output.free();
-
- /* for displacement method both, we only need to recompute the face
- * normals, as bump mapping in the shader will already alter the
- * vertex normal, so we start from the non-displaced vertex normals
- * to avoid applying the perturbation twice. */
- mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
- mesh->add_face_normals();
-
- bool need_recompute_vertex_normals = false;
-
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
- need_recompute_vertex_normals = true;
- break;
- }
- }
-
- if(need_recompute_vertex_normals) {
- bool flip = mesh->transform_negative_scaled;
- vector<bool> tri_has_true_disp(num_triangles, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- tri_has_true_disp[i] = shader->has_displacement && shader->displacement_method == DISPLACE_TRUE;
- }
-
- /* static vertex normals */
-
- /* get attributes */
- Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
- Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
-
- float3 *fN = attr_fN->data_float3();
- float3 *vN = attr_vN->data_float3();
-
- /* compute vertex normals */
-
- /* zero vertex normals on triangles with true displacement */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
- }
-
- /* add face normals to vertex normals */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- vN[mesh->get_triangle(i).v[j]] += fN[i];
- }
- }
- }
-
- /* normalize vertex normals */
- done.clear();
- done.resize(num_verts, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- int vert = mesh->get_triangle(i).v[j];
-
- if(done[vert]) {
- continue;
- }
-
- vN[vert] = normalize(vN[vert]);
- if(flip)
- vN[vert] = -vN[vert];
-
- done[vert] = true;
- }
- }
- }
-
- /* motion vertex normals */
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if(mesh->has_motion_blur() && attr_mP && attr_mN) {
- for(int step = 0; step < mesh->motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*mesh->verts.size();
- float3 *mN = attr_mN->data_float3() + step*mesh->verts.size();
-
- /* compute */
-
- /* zero vertex normals on triangles with true displacement */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
- }
-
- /* add face normals to vertex normals */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
- mN[mesh->get_triangle(i).v[j]] += fN;
- }
- }
- }
-
- /* normalize vertex normals */
- done.clear();
- done.resize(num_verts, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- int vert = mesh->get_triangle(i).v[j];
-
- if(done[vert]) {
- continue;
- }
-
- mN[vert] = normalize(mN[vert]);
- if(flip)
- mN[vert] = -mN[vert];
-
- done[vert] = true;
- }
- }
- }
- }
- }
- }
-
- return true;
+ /* verify if we have a displacement shader */
+ if (!mesh->has_true_displacement()) {
+ return false;
+ }
+
+ string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
+ progress.set_status("Updating Mesh", msg);
+
+ /* find object index. todo: is arbitrary */
+ size_t object_index = OBJECT_NONE;
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ if (scene->objects[i]->mesh == mesh) {
+ object_index = i;
+ break;
+ }
+ }
+
+ /* setup input for device task */
+ const size_t num_verts = mesh->verts.size();
+ vector<bool> done(num_verts, false);
+ device_vector<uint4> d_input(device, "displace_input", MEM_READ_ONLY);
+ uint4 *d_input_data = d_input.alloc(num_verts);
+ size_t d_input_size = 0;
+
+ size_t num_triangles = mesh->num_triangles();
+ for (size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ if (done[t.v[j]])
+ continue;
+
+ done[t.v[j]] = true;
+
+ /* set up object, primitive and barycentric coordinates */
+ int object = object_index;
+ int prim = mesh->tri_offset + i;
+ float u, v;
+
+ switch (j) {
+ case 0:
+ u = 1.0f;
+ v = 0.0f;
+ break;
+ case 1:
+ u = 0.0f;
+ v = 1.0f;
+ break;
+ default:
+ u = 0.0f;
+ v = 0.0f;
+ break;
+ }
+
+ /* back */
+ uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
+ d_input_data[d_input_size++] = in;
+ }
+ }
+
+ if (d_input_size == 0)
+ return false;
+
+ /* run device task */
+ device_vector<float4> d_output(device, "displace_output", MEM_READ_WRITE);
+ d_output.alloc(d_input_size);
+ d_output.zero_to_device();
+ d_input.copy_to_device();
+
+ /* needs to be up to data for attribute access */
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_input = d_input.device_pointer;
+ task.shader_output = d_output.device_pointer;
+ task.shader_eval_type = SHADER_EVAL_DISPLACE;
+ task.shader_x = 0;
+ task.shader_w = d_output.size();
+ task.num_samples = 1;
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+
+ device->task_add(task);
+ device->task_wait();
+
+ if (progress.get_cancel()) {
+ d_input.free();
+ d_output.free();
+ return false;
+ }
+
+ d_output.copy_from_device(0, 1, d_output.size());
+ d_input.free();
+
+ /* read result */
+ done.clear();
+ done.resize(num_verts, false);
+ int k = 0;
+
+ float4 *offset = d_output.data();
+
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ for (size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ if (!done[t.v[j]]) {
+ done[t.v[j]] = true;
+ float3 off = float4_to_float3(offset[k++]);
+ /* Avoid illegal vertex coordinates. */
+ off = ensure_finite3(off);
+ mesh->verts[t.v[j]] += off;
+ if (attr_mP != NULL) {
+ for (int step = 0; step < mesh->motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * num_verts;
+ mP[t.v[j]] += off;
+ }
+ }
+ }
+ }
+ }
+
+ d_output.free();
+
+ /* for displacement method both, we only need to recompute the face
+ * normals, as bump mapping in the shader will already alter the
+ * vertex normal, so we start from the non-displaced vertex normals
+ * to avoid applying the perturbation twice. */
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+
+ bool need_recompute_vertex_normals = false;
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
+ need_recompute_vertex_normals = true;
+ break;
+ }
+ }
+
+ if (need_recompute_vertex_normals) {
+ bool flip = mesh->transform_negative_scaled;
+ vector<bool> tri_has_true_disp(num_triangles, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ tri_has_true_disp[i] = shader->has_displacement &&
+ shader->displacement_method == DISPLACE_TRUE;
+ }
+
+ /* static vertex normals */
+
+ /* get attributes */
+ Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
+ Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
+
+ float3 *fN = attr_fN->data_float3();
+ float3 *vN = attr_vN->data_float3();
+
+ /* compute vertex normals */
+
+ /* zero vertex normals on triangles with true displacement */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ /* add face normals to vertex normals */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[mesh->get_triangle(i).v[j]] += fN[i];
+ }
+ }
+ }
+
+ /* normalize vertex normals */
+ done.clear();
+ done.resize(num_verts, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ int vert = mesh->get_triangle(i).v[j];
+
+ if (done[vert]) {
+ continue;
+ }
+
+ vN[vert] = normalize(vN[vert]);
+ if (flip)
+ vN[vert] = -vN[vert];
+
+ done[vert] = true;
+ }
+ }
+ }
+
+ /* motion vertex normals */
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (mesh->has_motion_blur() && attr_mP && attr_mN) {
+ for (int step = 0; step < mesh->motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * mesh->verts.size();
+ float3 *mN = attr_mN->data_float3() + step * mesh->verts.size();
+
+ /* compute */
+
+ /* zero vertex normals on triangles with true displacement */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ /* add face normals to vertex normals */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
+ mN[mesh->get_triangle(i).v[j]] += fN;
+ }
+ }
+ }
+
+ /* normalize vertex normals */
+ done.clear();
+ done.resize(num_verts, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ int vert = mesh->get_triangle(i).v[j];
+
+ if (done[vert]) {
+ continue;
+ }
+
+ mN[vert] = normalize(mN[vert]);
+ if (flip)
+ mN[vert] = -mN[vert];
+
+ done[vert] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
}
CCL_NAMESPACE_END