GPv3: Reverse Curve node #113702

Manually merged
Dalai Felinto merged 55 commits from dfelinto/blender:grease-nodes-reverted-node into main 2023-10-16 11:54:19 +02:00
2 changed files with 46 additions and 41 deletions
Showing only changes of commit ba89723abc - Show all commits

View File

@ -22,9 +22,9 @@
namespace blender::eevee {
bool VolumeModule::GridAABB::init(Object *ob, const Camera &camera, const VolumesInfoData &data)
VolumeModule::GridAABB::GridAABB(Object *ob, const Camera &camera, const VolumesInfoData &data)
{
/* Returns the unified volume grid cell index of a world space coordinate. */
/* Returns the unified volume grid cell corner of a world space coordinate. */
auto to_global_grid_coords = [&](float3 wP) -> int3 {
const float4x4 &view_matrix = camera.data_get().viewmat;
const float4x4 &projection_matrix = camera.data_get().winmat;
@ -38,41 +38,32 @@ bool VolumeModule::GridAABB::init(Object *ob, const Camera &camera, const Volume
data.depth_distribution,
data.coord_scale,
ndc_coords);
return int3(grid_coords * float3(data.tex_size));
/* Round to nearest grid corner. */
return int3(grid_coords * float3(data.tex_size) + 0.5);
};
const BoundBox &bbox = *BKE_object_boundbox_get(ob);
min = int3(INT32_MAX);
max = int3(INT32_MIN);
for (float3 corner : bbox.vec) {
corner = math::transform_point(float4x4(ob->object_to_world), corner);
int3 grid_coord = to_global_grid_coords(corner);
min = math::min(min, grid_coord);
max = math::max(max, grid_coord);
for (float3 l_corner : bbox.vec) {
float3 w_corner = math::transform_point(float4x4(ob->object_to_world), l_corner);
/* Note that this returns the nearest cell corner coordinate.
* So sub-froxel AABB will effectively return the same coordinate
* for each corner (making it empty and skipped) unless it
* cover the center of the froxel. */
math::min_max(to_global_grid_coords(w_corner), min, max);
}
bool is_visible = false;
for (int i : IndexRange(3)) {
is_visible = is_visible || (min[i] >= 0 && min[i] < data.tex_size[i]);
is_visible = is_visible || (max[i] >= 0 && max[i] < data.tex_size[i]);
}
min = math::clamp(min, int3(0), data.tex_size);
max = math::clamp(max, int3(0), data.tex_size);
return is_visible;
}
bool VolumeModule::GridAABB::overlaps(const GridAABB &aabb)
bool VolumeModule::GridAABB::is_empty() const
{
for (int i : IndexRange(3)) {
if (min[i] > aabb.max[i] || max[i] < aabb.min[i]) {
return false;
}
}
return true;
return math::reduce_min(max - min) <= 0;
}
VolumeModule::GridAABB VolumeModule::GridAABB::intersect(const GridAABB &other) const
{
return {math::min(this->max, other.max), math::max(this->min, other.min)};
}
void VolumeModule::init()
@ -180,8 +171,11 @@ void VolumeModule::sync_object(Object *ob,
return;
}
GridAABB aabb;
if (!aabb.init(ob, inst_.camera, data_)) {
GridAABB object_aabb(ob, inst_.camera, data_);
/* Remember that these are cells corners, so this extents to `tex_size`. */
GridAABB view_aabb(int3(0), data_.tex_size);
if (object_aabb.intersect(view_aabb).is_empty()) {
/* Skip invisible object with respect to raster grid and bounds density. */
return;
}
@ -191,27 +185,25 @@ void VolumeModule::sync_object(Object *ob,
enabled_ = true;
/* Add a barrier at the start of a subpass or when 2 volumes overlaps. */
if (!subpass_aabbs_.contains_as(shader)) {
if (!subpass_aabbs_.contains_as(shader) == false) {
object_pass->barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
subpass_aabbs_.add(shader, {aabb});
subpass_aabbs_.add(shader, {object_aabb});
}
else {
Vector<GridAABB> &aabbs = subpass_aabbs_.lookup(shader);
for (GridAABB &_aabb : aabbs) {
if (aabb.overlaps(_aabb)) {
for (GridAABB &other_aabb : aabbs) {
if (object_aabb.intersect(other_aabb).is_empty() == false) {
object_pass->barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
aabbs.clear();
break;
}
}
aabbs.append(aabb);
aabbs.append(object_aabb);
}
int3 grid_size = aabb.max - aabb.min + int3(1);
object_pass->push_constant("drw_ResourceID", int(res_handle.resource_index()));
object_pass->push_constant("grid_coords_min", aabb.min);
object_pass->dispatch(math::divide_ceil(grid_size, int3(VOLUME_GROUP_SIZE)));
object_pass->push_constant("grid_coords_min", object_aabb.min);
object_pass->dispatch(math::divide_ceil(object_aabb.extent(), int3(VOLUME_GROUP_SIZE)));
}
}

View File

@ -79,12 +79,25 @@ class VolumeModule {
/* Axis aligned bounding box in the volume grid.
* Used for frustum culling and volumes overlapping detection. */
struct GridAABB {
/* Represent min and max grid corners covered by a volume.
* So a volume covering the first froxel will have min={0,0,0} and max={1,1,1}.
* A volume with min={0,0,0} and max={0,0,0} covers nothing. */
int3 min, max;
/* Returns true if visible. */
bool init(Object *ob, const Camera &camera, const VolumesInfoData &data);
GridAABB(int3 min_, int3 max_) : min(min_), max(max_){};
GridAABB(Object *ob, const Camera &camera, const VolumesInfoData &data);
bool overlaps(const GridAABB &aabb);
/** Returns the intersection between this AABB and the \a other AABB. */
GridAABB intersect(const GridAABB &other) const;
/** Returns true if volume covers no froxel. */
bool is_empty() const;
/** Returns the extent of the volume. */
int3 extent() const
{
return max - min;
}
};
/* Stores a vector of volume AABBs for each material pass,
* so we can detect overlapping volumes and place GPU barriers where needed