forked from bartvdbraak/blender
Cycles: remove surface area computation for meshes with OSL
This is relatively expensive and as per the OSL spec, this value is not expected to be meaningful for non-light shaders. This makes viewport updates a little faster. As a side effect also fixes T82723, viewport refresh issue with volume density.
This commit is contained in:
parent
c4f8aedbc2
commit
29cd99e7fd
@ -214,13 +214,6 @@ ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Total surface area of object */
|
|
||||||
|
|
||||||
ccl_device_inline float object_surface_area(KernelGlobals *kg, int object)
|
|
||||||
{
|
|
||||||
return kernel_tex_fetch(__objects, object).surface_area;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Color of the object */
|
/* Color of the object */
|
||||||
|
|
||||||
ccl_device_inline float3 object_color(KernelGlobals *kg, int object)
|
ccl_device_inline float3 object_color(KernelGlobals *kg, int object)
|
||||||
@ -328,7 +321,7 @@ ccl_device_inline float object_volume_density(KernelGlobals *kg, int object)
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return kernel_tex_fetch(__objects, object).surface_area;
|
return kernel_tex_fetch(__objects, object).volume_density;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device_inline float object_volume_step_size(KernelGlobals *kg, int object)
|
ccl_device_inline float object_volume_step_size(KernelGlobals *kg, int object)
|
||||||
|
@ -1461,7 +1461,7 @@ typedef struct KernelObject {
|
|||||||
Transform tfm;
|
Transform tfm;
|
||||||
Transform itfm;
|
Transform itfm;
|
||||||
|
|
||||||
float surface_area;
|
float volume_density;
|
||||||
float pass_id;
|
float pass_id;
|
||||||
float random_number;
|
float random_number;
|
||||||
float color[3];
|
float color[3];
|
||||||
|
@ -109,7 +109,7 @@ static void shaderdata_to_shaderglobals(
|
|||||||
globals->dvdy = sd->dv.dy;
|
globals->dvdy = sd->dv.dy;
|
||||||
globals->dPdu = TO_VEC3(sd->dPdu);
|
globals->dPdu = TO_VEC3(sd->dPdu);
|
||||||
globals->dPdv = TO_VEC3(sd->dPdv);
|
globals->dPdv = TO_VEC3(sd->dPdv);
|
||||||
globals->surfacearea = (sd->object == OBJECT_NONE) ? 1.0f : object_surface_area(kg, sd->object);
|
globals->surfacearea = 1.0f;
|
||||||
globals->time = sd->time;
|
globals->time = sd->time;
|
||||||
|
|
||||||
/* booleans */
|
/* booleans */
|
||||||
|
@ -55,12 +55,6 @@ struct UpdateObjectTransformState {
|
|||||||
*/
|
*/
|
||||||
map<ParticleSystem *, int> particle_offset;
|
map<ParticleSystem *, int> particle_offset;
|
||||||
|
|
||||||
/* Mesh area.
|
|
||||||
* Used to avoid calculation of mesh area multiple times. Used for both
|
|
||||||
* read and write. Acquire surface_area_lock to keep it all thread safe.
|
|
||||||
*/
|
|
||||||
map<Mesh *, float> surface_area_map;
|
|
||||||
|
|
||||||
/* Motion offsets for each object. */
|
/* Motion offsets for each object. */
|
||||||
array<uint> motion_offset;
|
array<uint> motion_offset;
|
||||||
|
|
||||||
@ -76,12 +70,8 @@ struct UpdateObjectTransformState {
|
|||||||
bool have_curves;
|
bool have_curves;
|
||||||
|
|
||||||
/* ** Scheduling queue. ** */
|
/* ** Scheduling queue. ** */
|
||||||
|
|
||||||
Scene *scene;
|
Scene *scene;
|
||||||
|
|
||||||
/* Some locks to keep everything thread-safe. */
|
|
||||||
thread_spin_lock surface_area_lock;
|
|
||||||
|
|
||||||
/* First unused object index in the queue. */
|
/* First unused object index in the queue. */
|
||||||
int queue_start_object;
|
int queue_start_object;
|
||||||
};
|
};
|
||||||
@ -379,80 +369,19 @@ ObjectManager::~ObjectManager()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static float object_surface_area(UpdateObjectTransformState *state,
|
static float object_volume_density(UpdateObjectTransformState *state,
|
||||||
const Transform &tfm,
|
const Transform &tfm,
|
||||||
Geometry *geom)
|
Geometry *geom)
|
||||||
{
|
{
|
||||||
if (geom->geometry_type != Geometry::MESH && geom->geometry_type != Geometry::VOLUME) {
|
if (geom->geometry_type == Geometry::VOLUME) {
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
|
||||||
if (mesh->has_volume || geom->geometry_type == Geometry::VOLUME) {
|
|
||||||
/* Volume density automatically adjust to object scale. */
|
/* Volume density automatically adjust to object scale. */
|
||||||
if (geom->geometry_type == Geometry::VOLUME &&
|
if (static_cast<Volume *>(geom)->get_object_space()) {
|
||||||
static_cast<Volume *>(geom)->get_object_space()) {
|
|
||||||
const float3 unit = normalize(make_float3(1.0f, 1.0f, 1.0f));
|
const float3 unit = normalize(make_float3(1.0f, 1.0f, 1.0f));
|
||||||
return 1.0f / len(transform_direction(&tfm, unit));
|
return 1.0f / len(transform_direction(&tfm, unit));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return 1.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute surface area. for uniform scale we can do avoid the many
|
return 1.0f;
|
||||||
* transform calls and share computation for instances.
|
|
||||||
*
|
|
||||||
* TODO(brecht): Correct for displacement, and move to a better place.
|
|
||||||
*/
|
|
||||||
float surface_area = 0.0f;
|
|
||||||
float uniform_scale;
|
|
||||||
if (transform_uniform_scale(tfm, uniform_scale)) {
|
|
||||||
map<Mesh *, float>::iterator it;
|
|
||||||
|
|
||||||
/* NOTE: This isn't fully optimal and could in theory lead to multiple
|
|
||||||
* threads calculating area of the same mesh in parallel. However, this
|
|
||||||
* also prevents suspending all the threads when some mesh's area is
|
|
||||||
* not yet known.
|
|
||||||
*/
|
|
||||||
state->surface_area_lock.lock();
|
|
||||||
it = state->surface_area_map.find(mesh);
|
|
||||||
state->surface_area_lock.unlock();
|
|
||||||
|
|
||||||
if (it == state->surface_area_map.end()) {
|
|
||||||
size_t num_triangles = mesh->num_triangles();
|
|
||||||
for (size_t j = 0; j < num_triangles; j++) {
|
|
||||||
Mesh::Triangle t = mesh->get_triangle(j);
|
|
||||||
float3 p1 = mesh->get_verts()[t.v[0]];
|
|
||||||
float3 p2 = mesh->get_verts()[t.v[1]];
|
|
||||||
float3 p3 = mesh->get_verts()[t.v[2]];
|
|
||||||
|
|
||||||
surface_area += triangle_area(p1, p2, p3);
|
|
||||||
}
|
|
||||||
|
|
||||||
state->surface_area_lock.lock();
|
|
||||||
state->surface_area_map[mesh] = surface_area;
|
|
||||||
state->surface_area_lock.unlock();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
surface_area = it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
surface_area *= uniform_scale;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
size_t num_triangles = mesh->num_triangles();
|
|
||||||
for (size_t j = 0; j < num_triangles; j++) {
|
|
||||||
Mesh::Triangle t = mesh->get_triangle(j);
|
|
||||||
float3 p1 = transform_point(&tfm, mesh->get_verts()[t.v[0]]);
|
|
||||||
float3 p2 = transform_point(&tfm, mesh->get_verts()[t.v[1]]);
|
|
||||||
float3 p3 = transform_point(&tfm, mesh->get_verts()[t.v[2]]);
|
|
||||||
|
|
||||||
surface_area += triangle_area(p1, p2, p3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return surface_area;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob)
|
void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob)
|
||||||
@ -476,7 +405,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
|
|||||||
|
|
||||||
kobject.tfm = tfm;
|
kobject.tfm = tfm;
|
||||||
kobject.itfm = itfm;
|
kobject.itfm = itfm;
|
||||||
kobject.surface_area = object_surface_area(state, tfm, geom);
|
kobject.volume_density = object_volume_density(state, tfm, geom);
|
||||||
kobject.color[0] = color.x;
|
kobject.color[0] = color.x;
|
||||||
kobject.color[1] = color.y;
|
kobject.color[1] = color.y;
|
||||||
kobject.color[2] = color.z;
|
kobject.color[2] = color.z;
|
||||||
|
Loading…
Reference in New Issue
Block a user