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.cpp')
-rw-r--r--intern/cycles/render/mesh.cpp306
1 files changed, 262 insertions, 44 deletions
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 5602609c030..57f194651f8 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "bvh.h"
@@ -20,9 +20,11 @@
#include "camera.h"
#include "curves.h"
#include "device.h"
+#include "graph.h"
#include "shader.h"
#include "light.h"
#include "mesh.h"
+#include "nodes.h"
#include "object.h"
#include "scene.h"
@@ -30,6 +32,7 @@
#include "util_cache.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_progress.h"
#include "util_set.h"
@@ -93,6 +96,8 @@ Mesh::Mesh()
attributes.triangle_mesh = this;
curve_attributes.curve_mesh = this;
+
+ has_volume = false;
}
Mesh::~Mesh()
@@ -132,7 +137,7 @@ void Mesh::clear()
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();
- geometry_synced = false;
+ geometry_flags = GEOMETRY_NONE;
}
int Mesh::split_vertex(int vertex)
@@ -207,11 +212,11 @@ void Mesh::compute_bounds()
bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w);
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (use_motion_blur && attr) {
+ if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow(vert_steps[i]);
}
@@ -220,7 +225,7 @@ void Mesh::compute_bounds()
size_t steps_size = curve_keys.size() * (motion_steps - 1);
float3 *key_steps = curve_attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow(key_steps[i]);
}
@@ -234,19 +239,19 @@ void Mesh::compute_bounds()
for(size_t i = 0; i < curve_keys_size; i++)
bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w);
- if (use_motion_blur && attr) {
+ if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow_safe(vert_steps[i]);
}
- if (use_motion_blur && curve_attr) {
+ if(use_motion_blur && curve_attr) {
size_t steps_size = curve_keys.size() * (motion_steps - 1);
float3 *key_steps = curve_attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow_safe(key_steps[i]);
}
}
@@ -508,7 +513,6 @@ void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total
progress->set_status(msg, "Building BVH");
BVHParams bparams;
- bparams.use_cache = params->use_bvh_cache;
bparams.use_spatial_split = params->use_bvh_spatial_split;
bparams.use_qbvh = params->use_qbvh;
@@ -553,6 +557,7 @@ MeshManager::MeshManager()
{
bvh = NULL;
need_update = true;
+ need_flags_update = true;
}
MeshManager::~MeshManager()
@@ -649,6 +654,10 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
}
}
}
+#else
+ (void)device;
+ (void)scene;
+ (void)mesh_attributes;
#endif
}
@@ -746,8 +755,49 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
device->tex_alloc("__attributes_map", dscene->attributes_map);
}
-static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_float, vector<float4>& attr_float3, vector<uchar4>& attr_uchar4,
- Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element)
+static void update_attribute_element_size(Mesh *mesh,
+ Attribute *mattr,
+ size_t *attr_float_size,
+ size_t *attr_float3_size,
+ size_t *attr_uchar4_size)
+{
+ if(mattr) {
+ size_t size = mattr->element_size(
+ mesh->verts.size(),
+ mesh->triangles.size(),
+ mesh->motion_steps,
+ mesh->curves.size(),
+ mesh->curve_keys.size());
+
+ if(mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* pass */
+ }
+ else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ *attr_uchar4_size += size;
+ }
+ else if(mattr->type == TypeDesc::TypeFloat) {
+ *attr_float_size += size;
+ }
+ else if(mattr->type == TypeDesc::TypeMatrix) {
+ *attr_float3_size += size * 4;
+ }
+ else {
+ *attr_float3_size += size;
+ }
+ }
+}
+
+static void update_attribute_element_offset(Mesh *mesh,
+ vector<float>& attr_float,
+ size_t& attr_float_offset,
+ vector<float4>& attr_float3,
+ size_t& attr_float3_offset,
+ vector<uchar4>& attr_uchar4,
+ size_t& attr_uchar4_offset,
+ Attribute *mattr,
+ TypeDesc& type,
+ int& offset,
+ AttributeElement& element)
{
if(mattr) {
/* store element and type */
@@ -769,39 +819,43 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa
}
else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
uchar4 *data = mattr->data_uchar4();
- offset = attr_uchar4.size();
-
- attr_uchar4.resize(attr_uchar4.size() + size);
+ offset = attr_uchar4_offset;
- for(size_t k = 0; k < size; k++)
+ assert(attr_uchar4.capacity() >= offset + size);
+ for(size_t k = 0; k < size; k++) {
attr_uchar4[offset+k] = data[k];
+ }
+ attr_uchar4_offset += size;
}
else if(mattr->type == TypeDesc::TypeFloat) {
float *data = mattr->data_float();
- offset = attr_float.size();
+ offset = attr_float_offset;
- attr_float.resize(attr_float.size() + size);
-
- for(size_t k = 0; k < size; k++)
+ assert(attr_float.capacity() >= offset + size);
+ for(size_t k = 0; k < size; k++) {
attr_float[offset+k] = data[k];
+ }
+ attr_float_offset += size;
}
else if(mattr->type == TypeDesc::TypeMatrix) {
Transform *tfm = mattr->data_transform();
- offset = attr_float3.size();
-
- attr_float3.resize(attr_float3.size() + size*4);
+ offset = attr_float3_offset;
- for(size_t k = 0; k < size*4; k++)
+ assert(attr_float3.capacity() >= offset + size * 4);
+ for(size_t k = 0; k < size*4; k++) {
attr_float3[offset+k] = (&tfm->x)[k];
+ }
+ attr_float3_offset += size * 4;
}
else {
float4 *data = mattr->data_float4();
- offset = attr_float3.size();
-
- attr_float3.resize(attr_float3.size() + size);
+ offset = attr_float3_offset;
- for(size_t k = 0; k < size; k++)
+ assert(attr_float3.capacity() >= offset + size);
+ for(size_t k = 0; k < size; k++) {
attr_float3[offset+k] = data[k];
+ }
+ attr_float3_offset += size;
}
/* mesh vertex/curve index is global, not per object, so we sneak
@@ -851,16 +905,16 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
/* mesh attribute are stored in a single array per data type. here we fill
* those arrays, and set the offset and element type to create attribute
* maps next */
- vector<float> attr_float;
- vector<float4> attr_float3;
- vector<uchar4> attr_uchar4;
+ /* Pre-allocate attributes to avoid arrays re-allocation which would
+ * take 2x of overall attribute memory usage.
+ */
+ size_t attr_float_size = 0;
+ size_t attr_float3_size = 0;
+ size_t attr_uchar4_size = 0;
for(size_t i = 0; i < scene->meshes.size(); i++) {
Mesh *mesh = scene->meshes[i];
AttributeRequestSet& attributes = mesh_attributes[i];
-
- /* todo: we now store std and name attributes from requests even if
- * they actually refer to the same mesh attributes, optimize */
foreach(AttributeRequest& req, attributes.requests) {
Attribute *triangle_mattr = mesh->attributes.find(req);
Attribute *curve_mattr = mesh->curve_attributes.find(req);
@@ -874,12 +928,56 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
}
- update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, triangle_mattr,
- req.triangle_type, req.triangle_offset, req.triangle_element);
+ update_attribute_element_size(mesh,
+ triangle_mattr,
+ &attr_float_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ update_attribute_element_size(mesh,
+ curve_mattr,
+ &attr_float_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ }
+ }
+
+ vector<float> attr_float(attr_float_size);
+ vector<float4> attr_float3(attr_float3_size);
+ vector<uchar4> attr_uchar4(attr_uchar4_size);
+
+ size_t attr_float_offset = 0;
+ size_t attr_float3_offset = 0;
+ size_t attr_uchar4_offset = 0;
+
+ /* Fill in attributes. */
+ for(size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet& attributes = mesh_attributes[i];
+
+ /* todo: we now store std and name attributes from requests even if
+ * they actually refer to the same mesh attributes, optimize */
+ foreach(AttributeRequest& req, attributes.requests) {
+ Attribute *triangle_mattr = mesh->attributes.find(req);
+ Attribute *curve_mattr = mesh->curve_attributes.find(req);
+
+ update_attribute_element_offset(mesh,
+ attr_float, attr_float_offset,
+ attr_float3, attr_float3_offset,
+ attr_uchar4, attr_uchar4_offset,
+ triangle_mattr,
+ req.triangle_type,
+ req.triangle_offset,
+ req.triangle_element);
+
+ update_attribute_element_offset(mesh,
+ attr_float, attr_float_offset,
+ attr_float3, attr_float3_offset,
+ attr_uchar4, attr_uchar4_offset,
+ curve_mattr,
+ req.curve_type,
+ req.curve_offset,
+ req.curve_element);
- update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, curve_mattr,
- req.curve_type, req.curve_offset, req.curve_element);
-
if(progress.get_cancel()) return;
}
}
@@ -978,11 +1076,13 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
/* bvh build */
progress.set_status("Updating Scene BVH", "Building");
+ VLOG(1) << (scene->params.use_qbvh ? "Using QBVH optimization structure"
+ : "Using regular BVH optimization structure");
+
BVHParams bparams;
bparams.top_level = true;
bparams.use_qbvh = scene->params.use_qbvh;
bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
- bparams.use_cache = scene->params.use_bvh_cache;
delete bvh;
bvh = BVH::create(bparams, scene->objects);
@@ -999,6 +1099,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->bvh_nodes.reference((float4*)&pack.nodes[0], pack.nodes.size());
device->tex_alloc("__bvh_nodes", dscene->bvh_nodes);
}
+ if(pack.leaf_nodes.size()) {
+ dscene->bvh_leaf_nodes.reference((float4*)&pack.leaf_nodes[0], pack.leaf_nodes.size());
+ device->tex_alloc("__bvh_leaf_nodes", dscene->bvh_leaf_nodes);
+ }
if(pack.object_node.size()) {
dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size());
device->tex_alloc("__object_node", dscene->object_node);
@@ -1025,18 +1129,91 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
}
dscene->data.bvh.root = pack.root_index;
+ dscene->data.bvh.use_qbvh = scene->params.use_qbvh;
+}
+
+void MeshManager::device_update_flags(Device * /*device*/,
+ DeviceScene * /*dscene*/,
+ Scene * scene,
+ Progress& /*progress*/)
+{
+ if(!need_update && !need_flags_update) {
+ return;
+ }
+ /* update flags */
+ foreach(Mesh *mesh, scene->meshes) {
+ mesh->has_volume = false;
+ foreach(uint shader, mesh->used_shaders) {
+ if(scene->shaders[shader]->has_volume) {
+ mesh->has_volume = true;
+ }
+ }
+ }
+ need_flags_update = false;
+}
+
+void MeshManager::device_update_displacement_images(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress)
+{
+ progress.set_status("Updating Displacement Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> bump_images;
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update) {
+ foreach(uint shader_index, mesh->used_shaders) {
+ Shader *shader = scene->shaders[shader_index];
+ if(shader->graph_bump == NULL) {
+ continue;
+ }
+ foreach(ShaderNode* node, shader->graph_bump->nodes) {
+ if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
+ continue;
+ }
+ if(device->info.pack_images) {
+ /* If device requires packed images we need to update all
+ * images now, even if they're not used for displacement.
+ */
+ image_manager->device_update(device,
+ dscene,
+ progress);
+ return;
+ }
+ ImageSlotNode *image_node = static_cast<ImageSlotNode*>(node);
+ int slot = image_node->slot;
+ if(slot != -1) {
+ bump_images.insert(slot);
+ }
+ }
+ }
+ }
+ }
+ foreach(int slot, bump_images) {
+ pool.push(function_bind(&ImageManager::device_update_slot,
+ image_manager,
+ device,
+ dscene,
+ slot,
+ &progress));
+ }
+ pool.wait_work();
}
void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
+
if(!need_update)
return;
/* update normals */
foreach(Mesh *mesh, scene->meshes) {
- foreach(uint shader, mesh->used_shaders)
+ foreach(uint shader, mesh->used_shaders) {
if(scene->shaders[shader]->need_update_attributes)
mesh->need_update = true;
+ }
if(mesh->need_update) {
mesh->add_face_normals();
@@ -1046,6 +1223,28 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
}
}
+ /* Update images needed for true displacement. */
+ bool need_displacement_images = false;
+ bool old_need_object_flags_update = false;
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update &&
+ mesh->displacement_method != Mesh::DISPLACE_BUMP)
+ {
+ need_displacement_images = true;
+ break;
+ }
+ }
+ if(need_displacement_images) {
+ VLOG(1) << "Updating images used for true displacement.";
+ device_update_displacement_images(device, dscene, scene, progress);
+ old_need_object_flags_update = scene->object_manager->need_flags_update;
+ scene->object_manager->device_update_flags(device,
+ dscene,
+ scene,
+ progress,
+ false);
+ }
+
/* device update */
device_free(device, dscene);
@@ -1087,13 +1286,19 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
foreach(Mesh *mesh, scene->meshes) {
if(mesh->need_update) {
- pool.push(function_bind(&Mesh::compute_bvh, mesh, &scene->params, &progress, i, num_bvh));
- i++;
+ pool.push(function_bind(&Mesh::compute_bvh,
+ mesh,
+ &scene->params,
+ &progress,
+ i,
+ num_bvh));
+ if(!mesh->transform_applied) {
+ i++;
+ }
}
}
pool.wait_work();
-
foreach(Shader *shader, scene->shaders)
shader->need_update_attributes = false;
@@ -1104,6 +1309,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
bool motion_blur = false;
#endif
+ /* update obejcts */
+ vector<Object *> volume_objects;
foreach(Object *object, scene->objects)
object->compute_bounds(motion_blur);
@@ -1112,11 +1319,22 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
device_update_bvh(device, dscene, scene, progress);
need_update = false;
+
+ if(need_displacement_images) {
+ /* Re-tag flags for update, so they're re-evaluated
+ * for meshes with correct bounding boxes.
+ *
+ * This wouldn't cause wrong results, just true
+ * displacement might be less optimal ot calculate.
+ */
+ scene->object_manager->need_flags_update = old_need_object_flags_update;
+ }
}
void MeshManager::device_free(Device *device, DeviceScene *dscene)
{
device->tex_free(dscene->bvh_nodes);
+ device->tex_free(dscene->bvh_leaf_nodes);
device->tex_free(dscene->object_node);
device->tex_free(dscene->tri_woop);
device->tex_free(dscene->prim_type);