Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/mesh_displace.cpp
| Show All 10 Lines | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | ||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| * See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | ||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #include "device/device.h" | #include "device/device.h" | ||||
| #include "integrator/shader_eval.h" | |||||
| #include "render/mesh.h" | #include "render/mesh.h" | ||||
| #include "render/object.h" | #include "render/object.h" | ||||
| #include "render/scene.h" | #include "render/scene.h" | ||||
| #include "render/shader.h" | #include "render/shader.h" | ||||
| #include "util/util_foreach.h" | #include "util/util_foreach.h" | ||||
| #include "util/util_map.h" | #include "util/util_map.h" | ||||
| #include "util/util_progress.h" | #include "util/util_progress.h" | ||||
| Show All 11 Lines | static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts) | ||||
| float normlen = len(norm); | float normlen = len(norm); | ||||
| if (normlen == 0.0f) | if (normlen == 0.0f) | ||||
| return make_float3(1.0f, 0.0f, 0.0f); | return make_float3(1.0f, 0.0f, 0.0f); | ||||
| return norm / normlen; | return norm / normlen; | ||||
| } | } | ||||
| bool GeometryManager::displace( | /* Fill in coordinates for mesh displacement shader evaluation on device. */ | ||||
| Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress) | static int fill_shader_input(const Scene *scene, | ||||
| const Mesh *mesh, | |||||
| const int object_index, | |||||
| device_vector<KernelShaderEvalInput> &d_input) | |||||
| { | { | ||||
| /* verify if we have a displacement shader */ | int d_input_size = 0; | ||||
| if (!mesh->has_true_displacement()) { | KernelShaderEvalInput *d_input_data = d_input.data(); | ||||
| 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 */ | const array<int> &mesh_shaders = mesh->get_shader(); | ||||
| size_t object_index = OBJECT_NONE; | const array<Node *> &mesh_used_shaders = mesh->get_used_shaders(); | ||||
| const array<float3> &mesh_verts = mesh->get_verts(); | |||||
| for (size_t i = 0; i < scene->objects.size(); i++) { | const int num_verts = mesh_verts.size(); | ||||
| if (scene->objects[i]->get_geometry() == mesh) { | |||||
| object_index = i; | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* setup input for device task */ | |||||
| const size_t num_verts = mesh->verts.size(); | |||||
| vector<bool> done(num_verts, false); | 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(); | int num_triangles = mesh->num_triangles(); | ||||
| for (size_t i = 0; i < num_triangles; i++) { | for (int i = 0; i < num_triangles; i++) { | ||||
| Mesh::Triangle t = mesh->get_triangle(i); | Mesh::Triangle t = mesh->get_triangle(i); | ||||
| int shader_index = mesh->shader[i]; | int shader_index = mesh_shaders[i]; | ||||
| Shader *shader = (shader_index < mesh->used_shaders.size()) ? | Shader *shader = (shader_index < mesh_used_shaders.size()) ? | ||||
| static_cast<Shader *>(mesh->used_shaders[shader_index]) : | static_cast<Shader *>(mesh_used_shaders[shader_index]) : | ||||
| scene->default_surface; | scene->default_surface; | ||||
| if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { | if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| for (int j = 0; j < 3; j++) { | for (int j = 0; j < 3; j++) { | ||||
| if (done[t.v[j]]) | if (done[t.v[j]]) | ||||
| Show All 17 Lines | for (int j = 0; j < 3; j++) { | ||||
| break; | break; | ||||
| default: | default: | ||||
| u = 0.0f; | u = 0.0f; | ||||
| v = 0.0f; | v = 0.0f; | ||||
| break; | break; | ||||
| } | } | ||||
| /* back */ | /* back */ | ||||
| uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v)); | KernelShaderEvalInput in; | ||||
| in.object = object; | |||||
| in.prim = prim; | |||||
| in.u = u; | |||||
| in.v = v; | |||||
| d_input_data[d_input_size++] = in; | d_input_data[d_input_size++] = in; | ||||
| } | } | ||||
| } | } | ||||
| if (d_input_size == 0) | return d_input_size; | ||||
| 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()); | /* Read back mesh displacement shader output. */ | ||||
| d_input.free(); | static void read_shader_output(const Scene *scene, | ||||
| Mesh *mesh, | |||||
| const device_vector<float4> &d_output) | |||||
| { | |||||
| const array<int> &mesh_shaders = mesh->get_shader(); | |||||
| const array<Node *> &mesh_used_shaders = mesh->get_used_shaders(); | |||||
| array<float3> &mesh_verts = mesh->get_verts(); | |||||
| /* read result */ | const int num_verts = mesh_verts.size(); | ||||
| done.clear(); | const int num_motion_steps = mesh->get_motion_steps(); | ||||
| done.resize(num_verts, false); | vector<bool> done(num_verts, false); | ||||
| int k = 0; | |||||
| float4 *offset = d_output.data(); | const float4 *d_output_data = d_output.data(); | ||||
| int d_output_index = 0; | |||||
| Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| for (size_t i = 0; i < num_triangles; i++) { | int num_triangles = mesh->num_triangles(); | ||||
| for (int i = 0; i < num_triangles; i++) { | |||||
| Mesh::Triangle t = mesh->get_triangle(i); | Mesh::Triangle t = mesh->get_triangle(i); | ||||
| int shader_index = mesh->shader[i]; | int shader_index = mesh_shaders[i]; | ||||
| Shader *shader = (shader_index < mesh->used_shaders.size()) ? | Shader *shader = (shader_index < mesh_used_shaders.size()) ? | ||||
| static_cast<Shader *>(mesh->used_shaders[shader_index]) : | static_cast<Shader *>(mesh_used_shaders[shader_index]) : | ||||
| scene->default_surface; | scene->default_surface; | ||||
| if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { | if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| for (int j = 0; j < 3; j++) { | for (int j = 0; j < 3; j++) { | ||||
| if (!done[t.v[j]]) { | if (!done[t.v[j]]) { | ||||
| done[t.v[j]] = true; | done[t.v[j]] = true; | ||||
| float3 off = float4_to_float3(offset[k++]); | float3 off = float4_to_float3(d_output_data[d_output_index++]); | ||||
| /* Avoid illegal vertex coordinates. */ | /* Avoid illegal vertex coordinates. */ | ||||
| off = ensure_finite3(off); | off = ensure_finite3(off); | ||||
| mesh->verts[t.v[j]] += off; | mesh_verts[t.v[j]] += off; | ||||
| if (attr_mP != NULL) { | if (attr_mP != NULL) { | ||||
| for (int step = 0; step < mesh->motion_steps - 1; step++) { | for (int step = 0; step < num_motion_steps - 1; step++) { | ||||
| float3 *mP = attr_mP->data_float3() + step * num_verts; | float3 *mP = attr_mP->data_float3() + step * num_verts; | ||||
| mP[t.v[j]] += off; | mP[t.v[j]] += off; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| bool GeometryManager::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; | |||||
| } | |||||
| const size_t num_verts = mesh->verts.size(); | |||||
| const size_t num_triangles = mesh->num_triangles(); | |||||
| if (num_triangles == 0) { | |||||
| return false; | |||||
| } | |||||
| d_output.free(); | 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]->get_geometry() == mesh) { | |||||
| object_index = i; | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* Needs to be up to data for attribute access. */ | |||||
| device->const_copy_to("__data", &dscene->data, sizeof(dscene->data)); | |||||
| /* Evaluate shader on device. */ | |||||
| ShaderEval shader_eval(device, progress); | |||||
| if (!shader_eval.eval(SHADER_EVAL_DISPLACE, | |||||
| num_verts, | |||||
| function_bind(&fill_shader_input, scene, mesh, object_index, _1), | |||||
| function_bind(&read_shader_output, scene, mesh, _1))) { | |||||
| return false; | |||||
| } | |||||
| /* stitch */ | /* stitch */ | ||||
| unordered_set<int> stitch_keys; | unordered_set<int> stitch_keys; | ||||
| for (pair<int, int> i : mesh->vert_to_stitching_key_map) { | for (pair<int, int> i : mesh->vert_to_stitching_key_map) { | ||||
| stitch_keys.insert(i.second); /* stitching index */ | stitch_keys.insert(i.second); /* stitching index */ | ||||
| } | } | ||||
| typedef unordered_multimap<int, int>::iterator map_it_t; | typedef unordered_multimap<int, int>::iterator map_it_t; | ||||
| ▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < num_triangles; i++) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* normalize vertex normals */ | /* normalize vertex normals */ | ||||
| done.clear(); | vector<bool> done(num_verts, false); | ||||
| done.resize(num_verts, false); | |||||
| for (size_t i = 0; i < num_triangles; i++) { | for (size_t i = 0; i < num_triangles; i++) { | ||||
| if (tri_has_true_disp[i]) { | if (tri_has_true_disp[i]) { | ||||
| for (size_t j = 0; j < 3; j++) { | for (size_t j = 0; j < 3; j++) { | ||||
| int vert = mesh->get_triangle(i).v[j]; | int vert = mesh->get_triangle(i).v[j]; | ||||
| if (done[vert]) { | if (done[vert]) { | ||||
| continue; | continue; | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | if (mesh->has_motion_blur() && attr_mP && attr_mN) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* normalize vertex normals */ | /* normalize vertex normals */ | ||||
| done.clear(); | vector<bool> done(num_verts, false); | ||||
| done.resize(num_verts, false); | |||||
| for (size_t i = 0; i < num_triangles; i++) { | for (size_t i = 0; i < num_triangles; i++) { | ||||
| if (tri_has_true_disp[i]) { | if (tri_has_true_disp[i]) { | ||||
| for (size_t j = 0; j < 3; j++) { | for (size_t j = 0; j < 3; j++) { | ||||
| int vert = mesh->get_triangle(i).v[j]; | int vert = mesh->get_triangle(i).v[j]; | ||||
| if (done[vert]) { | if (done[vert]) { | ||||
| continue; | continue; | ||||
| Show All 18 Lines | |||||