UI: show recently selected items at the top of searches #110828

Merged
Jacques Lucke merged 24 commits from JacquesLucke/blender:recent-searches into main 2023-09-25 10:56:20 +02:00
74 changed files with 1482 additions and 1010 deletions
Showing only changes of commit d14406e440 - Show all commits

View File

@ -192,8 +192,6 @@ set(PLATFORM_LINKFLAGS
"-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework Metal -framework QuartzCore"
)
list(APPEND PLATFORM_LINKLIBS c++)
if(WITH_OPENIMAGEDENOISE)
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
# OpenImageDenoise uses BNNS from the Accelerate framework.
@ -330,16 +328,6 @@ endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
find_package(Embree 3.8.0 REQUIRED)
# Embree static library linking can mix up SSE and AVX symbols, causing
# crashes on macOS systems with older CPUs that don't have AVX. Using
# force load avoids that. The Embree shared library does not suffer from
# this problem, precisely because linking a shared library uses force load.
set(_embree_libraries_force_load)
foreach(_embree_library ${EMBREE_LIBRARIES})
list(APPEND _embree_libraries_force_load "-Wl,-force_load,${_embree_library}")
endforeach()
set(EMBREE_LIBRARIES ${_embree_libraries_force_load})
endif()
add_bundled_libraries(embree/lib)
@ -435,8 +423,10 @@ string(APPEND PLATFORM_LINKFLAGS
" -Wl,-unexported_symbols_list,'${PLATFORM_SYMBOLS_MAP}'"
)
string(APPEND CMAKE_CXX_FLAGS " -stdlib=libc++")
string(APPEND PLATFORM_LINKFLAGS " -stdlib=libc++")
# Use old, slower linker for now to avoid many linker warnings.
if(${XCODE_VERSION} VERSION_GREATER_EQUAL 15.0)
string(APPEND PLATFORM_LINKFLAGS " -Wl,-ld_classic")
endif()
# Make stack size more similar to Embree, required for Embree.
string(APPEND PLATFORM_LINKFLAGS_EXECUTABLE " -Wl,-stack_size,0x100000")

View File

@ -4,6 +4,8 @@
buildbot:
gcc:
version: '11.0.0'
xcode:
version: '15.0'
cuda10:
version: '10.1.243'
cuda11:

View File

@ -108,7 +108,7 @@ class OUTLINER_MT_context_menu(Menu):
layout.separator()
layout.menu("OUTLINER_MT_liboverride")
layout.menu("OUTLINER_MT_liboverride", icon="LIBRARY_DATA_OVERRIDE")
layout.separator()

View File

@ -2634,7 +2634,7 @@ class VIEW3D_MT_object(Menu):
layout.menu("VIEW3D_MT_object_parent")
layout.menu("VIEW3D_MT_object_collection")
layout.menu("VIEW3D_MT_object_relations")
layout.menu("VIEW3D_MT_object_liboverride")
layout.menu("VIEW3D_MT_object_liboverride", icon="LIBRARY_DATA_OVERRIDE")
layout.menu("VIEW3D_MT_object_constraints")
layout.menu("VIEW3D_MT_object_track")
layout.menu("VIEW3D_MT_make_links")
@ -4308,9 +4308,9 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.menu("VIEW3D_MT_snap", text="Snap Vertices")
col.separator()
col.operator("transform.vert_crease")
col.separator()
# Removal Operators

View File

@ -741,11 +741,11 @@ inline const blender::bke::greasepencil::LayerGroup &GreasePencilLayerTreeGroup:
return *reinterpret_cast<const blender::bke::greasepencil::LayerGroup *>(this);
}
inline GreasePencilDrawingBase *GreasePencil::drawings(int64_t index) const
inline const GreasePencilDrawingBase *GreasePencil::drawing(int64_t index) const
{
return this->drawings()[index];
}
inline GreasePencilDrawingBase *GreasePencil::drawings(int64_t index)
inline GreasePencilDrawingBase *GreasePencil::drawing(int64_t index)
{
return this->drawings()[index];
}

View File

@ -322,6 +322,44 @@ extern bNodeTreeType NodeTreeTypeUndefined;
extern bNodeType NodeTypeUndefined;
extern bNodeSocketType NodeSocketTypeUndefined;
/**
* Contains information about a specific kind of zone (e.g. simulation or repeat zone in geometry
* nodes). This allows writing code that works for all kinds of zones automatically, reducing
* redundancy and the amount of boilerplate needed when adding a new zone type.
*/
class bNodeZoneType {
public:
std::string input_idname;
std::string output_idname;
int input_type;
int output_type;
int theme_id;
virtual ~bNodeZoneType() = default;
virtual const int &get_corresponding_output_id(const bNode &input_bnode) const = 0;
int &get_corresponding_output_id(bNode &input_bnode) const
{
return const_cast<int &>(
this->get_corresponding_output_id(const_cast<const bNode &>(input_bnode)));
}
const bNode *get_corresponding_input(const bNodeTree &tree, const bNode &output_bnode) const;
bNode *get_corresponding_input(bNodeTree &tree, const bNode &output_bnode) const;
const bNode *get_corresponding_output(const bNodeTree &tree, const bNode &input_bnode) const;
bNode *get_corresponding_output(bNodeTree &tree, const bNode &input_bnode) const;
};
void register_node_zone_type(const bNodeZoneType &zone_type);
Span<const bNodeZoneType *> all_zone_types();
Span<int> all_zone_node_types();
Span<int> all_zone_input_node_types();
Span<int> all_zone_output_node_types();
const bNodeZoneType *zone_type_by_node_type(const int node_type);
} // namespace blender::bke
#define NODE_STORAGE_FUNCS(StorageT) \

View File

@ -675,11 +675,11 @@ GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object
BLI_assert(ob_orig.type == OB_GREASE_PENCIL);
const GreasePencil &grease_pencil_orig = *static_cast<const GreasePencil *>(ob_orig.data);
GreasePencilDrawingBase *drawing_base = grease_pencil_orig.drawings(drawing_index);
const GreasePencilDrawingBase *drawing_base = grease_pencil_orig.drawing(drawing_index);
GeometryDeformation deformation;
if (drawing_base->type == GP_DRAWING) {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
const auto *drawing = reinterpret_cast<const GreasePencilDrawing *>(drawing_base);
/* Use the undeformed positions by default. */
deformation.positions = drawing->wrap().strokes().positions();
}

View File

@ -1235,10 +1235,9 @@ Material *BKE_grease_pencil_object_material_ensure_by_name(Main *bmain,
static bool grease_pencil_references_cyclic_check_internal(const GreasePencil *id_reference,
const GreasePencil *grease_pencil)
{
for (GreasePencilDrawingBase *base : grease_pencil->drawings()) {
for (const GreasePencilDrawingBase *base : grease_pencil->drawings()) {
if (base->type == GP_DRAWING_REFERENCE) {
GreasePencilDrawingReference *reference = reinterpret_cast<GreasePencilDrawingReference *>(
base);
const auto *reference = reinterpret_cast<const GreasePencilDrawingReference *>(base);
if (id_reference == reference->id_reference) {
return true;
}
@ -1331,7 +1330,7 @@ template<typename T> static void shrink_array(T **array, int *num, const int shr
*num = new_array_num;
}
blender::Span<GreasePencilDrawingBase *> GreasePencil::drawings() const
blender::Span<const GreasePencilDrawingBase *> GreasePencil::drawings() const
{
return blender::Span<GreasePencilDrawingBase *>{this->drawing_array, this->drawing_array_num};
}
@ -1413,7 +1412,7 @@ bool GreasePencil::insert_duplicate_frame(blender::bke::greasepencil::Layer &lay
dst_frame->type = src_frame.type;
const GreasePencilDrawingBase *src_drawing_base = this->drawings(src_frame.drawing_index);
const GreasePencilDrawingBase *src_drawing_base = this->drawing(src_frame.drawing_index);
switch (src_drawing_base->type) {
case GP_DRAWING: {
const Drawing &src_drawing =
@ -1459,7 +1458,7 @@ bool GreasePencil::remove_frames(blender::bke::greasepencil::Layer &layer,
/* Null frames don't reference a drawing, continue. */
continue;
}
GreasePencilDrawingBase *drawing_base = this->drawings(drawing_index_to_remove);
GreasePencilDrawingBase *drawing_base = this->drawing(drawing_index_to_remove);
if (drawing_base->type != GP_DRAWING) {
/* If the drawing is referenced from another object, we don't track it's users because we
* cannot delete drawings from another object. */
@ -1516,13 +1515,14 @@ static void remove_drawings_unchecked(GreasePencil &grease_pencil,
}
}
/* Swap the pointers to the drawings in the drawing array. */
std::swap(grease_pencil.drawings()[index_to_remove], grease_pencil.drawings()[swap_index]);
std::swap(grease_pencil.drawing_array[index_to_remove],
grease_pencil.drawing_array[swap_index]);
next_available_index--;
}
/* Free the last drawings. */
for (const int64_t drawing_index : last_drawings_range) {
GreasePencilDrawingBase *drawing_base_to_remove = grease_pencil.drawings(drawing_index);
GreasePencilDrawingBase *drawing_base_to_remove = grease_pencil.drawing(drawing_index);
switch (drawing_base_to_remove->type) {
case GP_DRAWING: {
GreasePencilDrawing *drawing_to_remove = reinterpret_cast<GreasePencilDrawing *>(
@ -1549,7 +1549,7 @@ void GreasePencil::remove_drawings_with_no_users()
using namespace blender;
Vector<int64_t> drawings_to_be_removed;
for (const int64_t drawing_i : this->drawings().index_range()) {
GreasePencilDrawingBase *drawing_base = this->drawings(drawing_i);
GreasePencilDrawingBase *drawing_base = this->drawing(drawing_i);
if (drawing_base->type != GP_DRAWING) {
continue;
}
@ -1605,7 +1605,7 @@ void GreasePencil::move_duplicate_frames(
/* Add and overwrite the frame at the destination number. */
if (layer.frames().contains(dst_frame_number)) {
GreasePencilFrame frame_to_overwrite = layer.frames().lookup(dst_frame_number);
GreasePencilDrawingBase *drawing_base = this->drawings(frame_to_overwrite.drawing_index);
GreasePencilDrawingBase *drawing_base = this->drawing(frame_to_overwrite.drawing_index);
if (drawing_base->type == GP_DRAWING) {
reinterpret_cast<GreasePencilDrawing *>(drawing_base)->wrap().remove_user();
}
@ -1620,7 +1620,7 @@ void GreasePencil::move_duplicate_frames(
}
blender::bke::greasepencil::Drawing *GreasePencil::get_editable_drawing_at(
const blender::bke::greasepencil::Layer *layer, const int frame_number) const
const blender::bke::greasepencil::Layer *layer, const int frame_number)
{
if (layer == nullptr || !layer->is_editable()) {
return nullptr;
@ -1631,7 +1631,7 @@ blender::bke::greasepencil::Drawing *GreasePencil::get_editable_drawing_at(
/* No drawing found. */
return nullptr;
}
GreasePencilDrawingBase *drawing_base = this->drawings(drawing_index);
GreasePencilDrawingBase *drawing_base = this->drawing(drawing_index);
if (drawing_base->type != GP_DRAWING) {
/* Drawing references are not editable. */
return nullptr;
@ -1694,7 +1694,7 @@ static void foreach_drawing_ex(
{
using namespace blender::bke::greasepencil;
blender::Span<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
blender::Span<const GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
for (const Layer *layer : grease_pencil.layers()) {
switch (mode) {
case VISIBLE: {
@ -1997,7 +1997,7 @@ void GreasePencil::remove_layer(blender::bke::greasepencil::Layer &layer)
/* Remove drawings. */
for (GreasePencilFrame frame : layer.frames_for_write().values()) {
GreasePencilDrawingBase *drawing_base = this->drawings(frame.drawing_index);
GreasePencilDrawingBase *drawing_base = this->drawing(frame.drawing_index);
if (drawing_base->type != GP_DRAWING) {
continue;
}

View File

@ -61,8 +61,7 @@ TEST(greasepencil, remove_drawings)
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(BKE_id_new(ctx.bmain, ID_GP, "GP"));
grease_pencil.add_empty_drawings(3);
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(
grease_pencil.drawings(1));
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(grease_pencil.drawing(1));
drawing->wrap().strokes_for_write().resize(0, 10);
Layer &layer1 = grease_pencil.root_group().add_layer("Layer1");

View File

@ -285,25 +285,15 @@ struct ToposortNodeState {
static Vector<const bNode *> get_implicit_origin_nodes(const bNodeTree &ntree, bNode &node)
{
Vector<const bNode *> origin_nodes;
if (node.type == GEO_NODE_SIMULATION_OUTPUT) {
for (const bNode *sim_input_node :
ntree.runtime->nodes_by_type.lookup(nodeTypeFind("GeometryNodeSimulationInput")))
if (all_zone_output_node_types().contains(node.type)) {
const bNodeZoneType &zone_type = *zone_type_by_node_type(node.type);
/* Can't use #zone_type.get_corresponding_input because that expects the topology cache to be
* build already, but we are still building it here. */
for (const bNode *input_node :
ntree.runtime->nodes_by_type.lookup(nodeTypeFind(zone_type.input_idname.c_str())))
{
const auto &storage = *static_cast<const NodeGeometrySimulationInput *>(
sim_input_node->storage);
if (storage.output_node_id == node.identifier) {
origin_nodes.append(sim_input_node);
}
}
}
if (node.type == GEO_NODE_REPEAT_OUTPUT) {
for (const bNode *repeat_input_node :
ntree.runtime->nodes_by_type.lookup(nodeTypeFind("GeometryNodeRepeatInput")))
{
const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(
repeat_input_node->storage);
if (storage.output_node_id == node.identifier) {
origin_nodes.append(repeat_input_node);
if (zone_type.get_corresponding_output_id(*input_node) == node.identifier) {
origin_nodes.append(input_node);
}
}
}
@ -313,16 +303,10 @@ static Vector<const bNode *> get_implicit_origin_nodes(const bNodeTree &ntree, b
static Vector<const bNode *> get_implicit_target_nodes(const bNodeTree &ntree, bNode &node)
{
Vector<const bNode *> target_nodes;
if (node.type == GEO_NODE_SIMULATION_INPUT) {
const auto &storage = *static_cast<const NodeGeometrySimulationInput *>(node.storage);
if (const bNode *sim_output_node = ntree.node_by_id(storage.output_node_id)) {
target_nodes.append(sim_output_node);
}
}
if (node.type == GEO_NODE_REPEAT_INPUT) {
const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(node.storage);
if (const bNode *repeat_output_node = ntree.node_by_id(storage.output_node_id)) {
target_nodes.append(repeat_output_node);
if (all_zone_input_node_types().contains(node.type)) {
const bNodeZoneType &zone_type = *zone_type_by_node_type(node.type);
if (const bNode *output_node = zone_type.get_corresponding_output(ntree, node)) {
target_nodes.append(output_node);
}
}
return target_nodes;

View File

@ -588,19 +588,9 @@ class NodeTreeMainUpdater {
}
}
/* Check paired simulation zone nodes. */
if (node.type == GEO_NODE_SIMULATION_INPUT) {
const NodeGeometrySimulationInput *data = static_cast<const NodeGeometrySimulationInput *>(
node.storage);
if (const bNode *output_node = ntree.node_by_id(data->output_node_id)) {
if (output_node->runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
return true;
}
}
}
if (node.type == GEO_NODE_REPEAT_INPUT) {
const NodeGeometryRepeatInput *data = static_cast<const NodeGeometryRepeatInput *>(
node.storage);
if (const bNode *output_node = ntree.node_by_id(data->output_node_id)) {
if (all_zone_input_node_types().contains(node.type)) {
const bNodeZoneType &zone_type = *zone_type_by_node_type(node.type);
if (const bNode *output_node = zone_type.get_corresponding_output(ntree, node)) {
if (output_node->runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
return true;
}

View File

@ -32,10 +32,13 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
bNodeTreeZones &owner,
Map<const bNode *, bNodeTreeZone *> &r_zone_by_inout_node)
{
const Span<const bNodeZoneType *> zone_types = all_zone_types();
Vector<std::unique_ptr<bNodeTreeZone>> zones;
Vector<const bNode *> zone_output_nodes;
zone_output_nodes.extend(tree.nodes_by_type("GeometryNodeSimulationOutput"));
zone_output_nodes.extend(tree.nodes_by_type("GeometryNodeRepeatOutput"));
for (const bNodeZoneType *zone_type : zone_types) {
zone_output_nodes.extend(tree.nodes_by_type(zone_type->output_idname));
}
for (const bNode *node : zone_output_nodes) {
auto zone = std::make_unique<bNodeTreeZone>();
zone->owner = &owner;
@ -44,21 +47,13 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
r_zone_by_inout_node.add(node, zone.get());
zones.append_and_get_index(std::move(zone));
}
for (const bNode *node : tree.nodes_by_type("GeometryNodeSimulationInput")) {
const auto &storage = *static_cast<NodeGeometrySimulationInput *>(node->storage);
if (const bNode *sim_output_node = tree.node_by_id(storage.output_node_id)) {
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(sim_output_node, nullptr)) {
zone->input_node = node;
r_zone_by_inout_node.add(node, zone);
}
}
}
for (const bNode *node : tree.nodes_by_type("GeometryNodeRepeatInput")) {
const auto &storage = *static_cast<NodeGeometryRepeatInput *>(node->storage);
if (const bNode *repeat_output_node = tree.node_by_id(storage.output_node_id)) {
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(repeat_output_node, nullptr)) {
zone->input_node = node;
r_zone_by_inout_node.add(node, zone);
for (const bNodeZoneType *zone_type : zone_types) {
for (const bNode *input_node : tree.nodes_by_type(zone_type->input_idname)) {
if (const bNode *output_node = zone_type->get_corresponding_output(tree, *input_node)) {
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(output_node, nullptr)) {
zone->input_node = input_node;
r_zone_by_inout_node.add(input_node, zone);
}
}
}
}
@ -223,6 +218,9 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
return {};
}
const Span<int> input_types = all_zone_input_node_types();
const Span<int> output_types = all_zone_output_node_types();
std::unique_ptr<bNodeTreeZones> tree_zones = std::make_unique<bNodeTreeZones>();
const Span<const bNode *> all_nodes = tree.all_nodes();
@ -257,13 +255,13 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
depend_on_output_flags |= depend_on_output_flag_array[from_node_i];
}
}
if (ELEM(node->type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_REPEAT_INPUT)) {
if (input_types.contains(node->type)) {
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
/* Now entering a zone, so set the corresponding bit. */
depend_on_input_flags[zone->index].set();
}
}
else if (ELEM(node->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_REPEAT_OUTPUT)) {
else if (output_types.contains(node->type)) {
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
/* The output is implicitly linked to the input, so also propagate the bits from there. */
if (const bNode *zone_input_node = zone->input_node) {
@ -430,4 +428,96 @@ Vector<const bNodeTreeZone *> bNodeTreeZones::get_zone_stack_for_node(const int
return zone_stack;
}
const bNode *bNodeZoneType::get_corresponding_input(const bNodeTree &tree,
const bNode &output_bnode) const
{
for (const bNode *node : tree.nodes_by_type(this->input_idname)) {
if (this->get_corresponding_output_id(*node) == output_bnode.identifier) {
return node;
}
}
return nullptr;
}
const bNode *bNodeZoneType::get_corresponding_output(const bNodeTree &tree,
const bNode &input_bnode) const
{
return tree.node_by_id(this->get_corresponding_output_id(input_bnode));
}
bNode *bNodeZoneType::get_corresponding_input(bNodeTree &tree, const bNode &output_bnode) const
{
return const_cast<bNode *>(
this->get_corresponding_input(const_cast<const bNodeTree &>(tree), output_bnode));
}
bNode *bNodeZoneType::get_corresponding_output(bNodeTree &tree, const bNode &input_bnode) const
{
return const_cast<bNode *>(
this->get_corresponding_output(const_cast<const bNodeTree &>(tree), input_bnode));
}
static Vector<const bNodeZoneType *> &get_zone_types_vector()
{
static Vector<const bNodeZoneType *> zone_types;
return zone_types;
};
void register_node_zone_type(const bNodeZoneType &zone_type)
{
get_zone_types_vector().append(&zone_type);
}
Span<const bNodeZoneType *> all_zone_types()
{
return get_zone_types_vector();
}
Span<int> all_zone_node_types()
{
static const Vector<int> node_types = []() {
Vector<int> node_types;
for (const bNodeZoneType *zone_type : all_zone_types()) {
node_types.append(zone_type->input_type);
node_types.append(zone_type->output_type);
}
return node_types;
}();
return node_types;
}
Span<int> all_zone_input_node_types()
{
static const Vector<int> node_types = []() {
Vector<int> node_types;
for (const bNodeZoneType *zone_type : all_zone_types()) {
node_types.append(zone_type->input_type);
}
return node_types;
}();
return node_types;
}
Span<int> all_zone_output_node_types()
{
static const Vector<int> node_types = []() {
Vector<int> node_types;
for (const bNodeZoneType *zone_type : all_zone_types()) {
node_types.append(zone_type->output_type);
}
return node_types;
}();
return node_types;
}
const bNodeZoneType *zone_type_by_node_type(const int node_type)
{
for (const bNodeZoneType *zone_type : all_zone_types()) {
if (ELEM(node_type, zone_type->input_type, zone_type->output_type)) {
return zone_type;
}
}
return nullptr;
}
} // namespace blender::bke

View File

@ -469,6 +469,8 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_debug_irradiance_grid_vert.glsl
engines/eevee_next/shaders/eevee_debug_irradiance_grid_frag.glsl
engines/eevee_next/shaders/eevee_deferred_light_frag.glsl
engines/eevee_next/shaders/eevee_deferred_capture_frag.glsl
engines/eevee_next/shaders/eevee_deferred_combine_frag.glsl
engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
engines/eevee_next/shaders/eevee_depth_of_field_bokeh_lut_comp.glsl
engines/eevee_next/shaders/eevee_depth_of_field_downsample_comp.glsl
@ -519,6 +521,7 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_motion_blur_gather_comp.glsl
engines/eevee_next/shaders/eevee_motion_blur_lib.glsl
engines/eevee_next/shaders/eevee_nodetree_lib.glsl
engines/eevee_next/shaders/eevee_octahedron_lib.glsl
engines/eevee_next/shaders/eevee_ray_denoise_bilateral_comp.glsl
engines/eevee_next/shaders/eevee_ray_denoise_spatial_comp.glsl
engines/eevee_next/shaders/eevee_ray_denoise_temporal_comp.glsl
@ -529,12 +532,12 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_ray_trace_fallback_comp.glsl
engines/eevee_next/shaders/eevee_ray_trace_screen_comp.glsl
engines/eevee_next/shaders/eevee_ray_trace_screen_lib.glsl
engines/eevee_next/shaders/eevee_octahedron_lib.glsl
engines/eevee_next/shaders/eevee_ray_types_lib.glsl
engines/eevee_next/shaders/eevee_reflection_probe_eval_lib.glsl
engines/eevee_next/shaders/eevee_reflection_probe_lib.glsl
engines/eevee_next/shaders/eevee_reflection_probe_remap_comp.glsl
engines/eevee_next/shaders/eevee_reflection_probe_update_irradiance_comp.glsl
engines/eevee_next/shaders/eevee_renderpass_lib.glsl
engines/eevee_next/shaders/eevee_sampling_lib.glsl
engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl
engines/eevee_next/shaders/eevee_shadow_lib.glsl

View File

@ -78,6 +78,8 @@
#define RAYTRACE_GROUP_SIZE 8
/* Keep this as a define to avoid shader variations. */
#define RAYTRACE_RADIANCE_FORMAT GPU_R11F_G11F_B10F
#define RAYTRACE_RAYTIME_FORMAT GPU_R32F
#define RAYTRACE_HORIZON_FORMAT GPU_R32UI
#define RAYTRACE_VARIANCE_FORMAT GPU_R16F
#define RAYTRACE_TILEMASK_FORMAT GPU_R8UI
@ -144,6 +146,7 @@
#define RBUFS_CRYPTOMATTE_SLOT 2
#define GBUF_CLOSURE_SLOT 3
#define GBUF_COLOR_SLOT 4
#define GBUF_HEADER_SLOT 5
/* Volume properties pass do not write to `rbufs`. Reuse the same bind points. */
#define VOLUME_PROP_SCATTERING_IMG_SLOT 0
#define VOLUME_PROP_EXTINCTION_IMG_SLOT 1

View File

@ -68,7 +68,8 @@ class Instance;
* Color degradation is expected to happen in this case.
*/
struct GBuffer {
/* TODO(fclem): Use texture from pool once they support texture array. */
/* TODO(fclem): Use texture from pool once they support texture array and layer views. */
Texture header_tx = {"GbufferHeader"};
Texture closure_tx = {"GbufferClosure"};
Texture color_tx = {"GbufferColor"};
@ -76,6 +77,7 @@ struct GBuffer {
{
const bool use_sss = (closure_bits_ & CLOSURE_SSS) != 0;
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
header_tx.ensure_2d(GPU_R8UI, extent, usage);
closure_tx.ensure_2d_array(GPU_RGBA16, extent, use_sss ? 3 : 2, usage);
color_tx.ensure_2d_array(GPU_RGB10_A2, extent, 2, usage);
}
@ -83,9 +85,17 @@ struct GBuffer {
void release()
{
/* TODO(fclem): Use texture from pool once they support texture array. */
// header_tx.release();
// closure_tx.release();
// color_tx.release();
}
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
{
pass->bind_texture("gbuf_header_tx", &header_tx);
pass->bind_texture("gbuf_closure_tx", &closure_tx);
pass->bind_texture("gbuf_color_tx", &color_tx);
}
};
} // namespace blender::eevee

View File

@ -50616,4 +50616,290 @@ const float btdf_ggx[16][64][64][1] = {
{0.484816f}, {0.489247f}, {0.493525f}, {0.497667f}, {0.501639f}, {0.505508f}, {0.509225f},
{0.512815f}}}};
const float burley_sss_profile[64][1] = {
{1.000000f}, {0.957576f}, {0.890814f}, {0.813161f}, {0.732056f}, {0.652729f}, {0.578802f},
{0.512565f}, {0.455203f}, {0.407017f}, {0.365151f}, {0.326306f}, {0.291256f}, {0.259690f},
{0.231309f}, {0.205831f}, {0.182989f}, {0.162537f}, {0.144246f}, {0.127905f}, {0.113320f},
{0.100316f}, {0.088730f}, {0.078418f}, {0.069247f}, {0.061096f}, {0.053858f}, {0.047435f},
{0.041740f}, {0.036693f}, {0.032225f}, {0.028272f}, {0.024776f}, {0.021688f}, {0.018961f},
{0.016556f}, {0.014436f}, {0.012569f}, {0.010926f}, {0.009482f}, {0.008213f}, {0.007100f},
{0.006124f}, {0.005270f}, {0.004523f}, {0.003871f}, {0.003302f}, {0.002806f}, {0.002375f},
{0.002002f}, {0.001678f}, {0.001398f}, {0.001156f}, {0.000948f}, {0.000770f}, {0.000617f},
{0.000487f}, {0.000376f}, {0.000283f}, {0.000204f}, {0.000138f}, {0.000083f}, {0.000037f},
{0.000000f}};
const float random_walk_sss_profile[64][1] = {
{1.000000f}, {0.760107f}, {0.611901f}, {0.513783f}, {0.444313f}, {0.392204f}, {0.351327f},
{0.318198f}, {0.290730f}, {0.267583f}, {0.247844f}, {0.230851f}, {0.216102f}, {0.203204f},
{0.191843f}, {0.181761f}, {0.172748f}, {0.164631f}, {0.157263f}, {0.150525f}, {0.144317f},
{0.138554f}, {0.133166f}, {0.128095f}, {0.123292f}, {0.118714f}, {0.114328f}, {0.110104f},
{0.106017f}, {0.102048f}, {0.098178f}, {0.094393f}, {0.090680f}, {0.087030f}, {0.083434f},
{0.079884f}, {0.076376f}, {0.072904f}, {0.069466f}, {0.066058f}, {0.062679f}, {0.059328f},
{0.056006f}, {0.052712f}, {0.049448f}, {0.046216f}, {0.043019f}, {0.039860f}, {0.036744f},
{0.033675f}, {0.030658f}, {0.027700f}, {0.024807f}, {0.021987f}, {0.019248f}, {0.016600f},
{0.014052f}, {0.011614f}, {0.009298f}, {0.007116f}, {0.005081f}, {0.003206f}, {0.001508f},
{0.000000f}};
#ifdef CYCLES_REFERENCE_LUT /* Used for fitting. */
const float cycles_burley_reference_sss_profile[256][3] = {
{1.001349f, 1.005129f, 1.003057f}, {0.996234f, 0.937970f, 0.832274f},
{0.984534f, 0.833079f, 0.636661f}, {0.968951f, 0.729798f, 0.483946f},
{0.951269f, 0.637867f, 0.369217f}, {0.931896f, 0.556278f, 0.280570f},
{0.911943f, 0.485904f, 0.212907f}, {0.890728f, 0.423777f, 0.160349f},
{0.868180f, 0.368947f, 0.119834f}, {0.846582f, 0.321790f, 0.089213f},
{0.823967f, 0.279777f, 0.065628f}, {0.799325f, 0.242143f, 0.047621f},
{0.775499f, 0.209422f, 0.034016f}, {0.750743f, 0.180285f, 0.023687f},
{0.724644f, 0.153768f, 0.015651f}, {0.694837f, 0.128887f, 0.009247f},
{0.649793f, 0.100032f, 0.002824f}, {0.609569f, 0.077227f, 0.000000f},
{0.593871f, 0.066654f, 0.000000f}, {0.577724f, 0.057329f, 0.000000f},
{0.563388f, 0.049366f, 0.000000f}, {0.548080f, 0.042173f, 0.000000f},
{0.533839f, 0.036029f, 0.000000f}, {0.518934f, 0.030586f, 0.000000f},
{0.503859f, 0.025775f, 0.000000f}, {0.488154f, 0.021467f, 0.000000f},
{0.471856f, 0.017675f, 0.000000f}, {0.456286f, 0.014305f, 0.000000f},
{0.440492f, 0.011402f, 0.000000f}, {0.423739f, 0.008708f, 0.000000f},
{0.405961f, 0.006242f, 0.000000f}, {0.383785f, 0.003919f, 0.000000f},
{0.355914f, 0.001515f, 0.000000f}, {0.330087f, 0.000000f, 0.000000f},
{0.322205f, 0.000000f, 0.000000f}, {0.313107f, 0.000000f, 0.000000f},
{0.305684f, 0.000000f, 0.000000f}, {0.298305f, 0.000000f, 0.000000f},
{0.290766f, 0.000000f, 0.000000f}, {0.284501f, 0.000000f, 0.000000f},
{0.277168f, 0.000000f, 0.000000f}, {0.270779f, 0.000000f, 0.000000f},
{0.264595f, 0.000000f, 0.000000f}, {0.257483f, 0.000000f, 0.000000f},
{0.251835f, 0.000000f, 0.000000f}, {0.245278f, 0.000000f, 0.000000f},
{0.238797f, 0.000000f, 0.000000f}, {0.232752f, 0.000000f, 0.000000f},
{0.226898f, 0.000000f, 0.000000f}, {0.221044f, 0.000000f, 0.000000f},
{0.215808f, 0.000000f, 0.000000f}, {0.209979f, 0.000000f, 0.000000f},
{0.205014f, 0.000000f, 0.000000f}, {0.199265f, 0.000000f, 0.000000f},
{0.194127f, 0.000000f, 0.000000f}, {0.189446f, 0.000000f, 0.000000f},
{0.184623f, 0.000000f, 0.000000f}, {0.179929f, 0.000000f, 0.000000f},
{0.175405f, 0.000000f, 0.000000f}, {0.170868f, 0.000000f, 0.000000f},
{0.166011f, 0.000000f, 0.000000f}, {0.161839f, 0.000000f, 0.000000f},
{0.157865f, 0.000000f, 0.000000f}, {0.153985f, 0.000000f, 0.000000f},
{0.149645f, 0.000000f, 0.000000f}, {0.145994f, 0.000000f, 0.000000f},
{0.142004f, 0.000000f, 0.000000f}, {0.138097f, 0.000000f, 0.000000f},
{0.134363f, 0.000000f, 0.000000f}, {0.130533f, 0.000000f, 0.000000f},
{0.127376f, 0.000000f, 0.000000f}, {0.124018f, 0.000000f, 0.000000f},
{0.120724f, 0.000000f, 0.000000f}, {0.117440f, 0.000000f, 0.000000f},
{0.114474f, 0.000000f, 0.000000f}, {0.110925f, 0.000000f, 0.000000f},
{0.107756f, 0.000000f, 0.000000f}, {0.104074f, 0.000000f, 0.000000f},
{0.101206f, 0.000000f, 0.000000f}, {0.098670f, 0.000000f, 0.000000f},
{0.095842f, 0.000000f, 0.000000f}, {0.093562f, 0.000000f, 0.000000f},
{0.090276f, 0.000000f, 0.000000f}, {0.087599f, 0.000000f, 0.000000f},
{0.085057f, 0.000000f, 0.000000f}, {0.082433f, 0.000000f, 0.000000f},
{0.080531f, 0.000000f, 0.000000f}, {0.078609f, 0.000000f, 0.000000f},
{0.076213f, 0.000000f, 0.000000f}, {0.074083f, 0.000000f, 0.000000f},
{0.072166f, 0.000000f, 0.000000f}, {0.069501f, 0.000000f, 0.000000f},
{0.067523f, 0.000000f, 0.000000f}, {0.065427f, 0.000000f, 0.000000f},
{0.063125f, 0.000000f, 0.000000f}, {0.061604f, 0.000000f, 0.000000f},
{0.059982f, 0.000000f, 0.000000f}, {0.058250f, 0.000000f, 0.000000f},
{0.056052f, 0.000000f, 0.000000f}, {0.054623f, 0.000000f, 0.000000f},
{0.053044f, 0.000000f, 0.000000f}, {0.051472f, 0.000000f, 0.000000f},
{0.049807f, 0.000000f, 0.000000f}, {0.048165f, 0.000000f, 0.000000f},
{0.046592f, 0.000000f, 0.000000f}, {0.045360f, 0.000000f, 0.000000f},
{0.044138f, 0.000000f, 0.000000f}, {0.043084f, 0.000000f, 0.000000f},
{0.041529f, 0.000000f, 0.000000f}, {0.040134f, 0.000000f, 0.000000f},
{0.038586f, 0.000000f, 0.000000f}, {0.037457f, 0.000000f, 0.000000f},
{0.036212f, 0.000000f, 0.000000f}, {0.034872f, 0.000000f, 0.000000f},
{0.033882f, 0.000000f, 0.000000f}, {0.032777f, 0.000000f, 0.000000f},
{0.031593f, 0.000000f, 0.000000f}, {0.030589f, 0.000000f, 0.000000f},
{0.029223f, 0.000000f, 0.000000f}, {0.028413f, 0.000000f, 0.000000f},
{0.027221f, 0.000000f, 0.000000f}, {0.026115f, 0.000000f, 0.000000f},
{0.025458f, 0.000000f, 0.000000f}, {0.024576f, 0.000000f, 0.000000f},
{0.023826f, 0.000000f, 0.000000f}, {0.022929f, 0.000000f, 0.000000f},
{0.022254f, 0.000000f, 0.000000f}, {0.021391f, 0.000000f, 0.000000f},
{0.020656f, 0.000000f, 0.000000f}, {0.019991f, 0.000000f, 0.000000f},
{0.019231f, 0.000000f, 0.000000f}, {0.018549f, 0.000000f, 0.000000f},
{0.017666f, 0.000000f, 0.000000f}, {0.017044f, 0.000000f, 0.000000f},
{0.016422f, 0.000000f, 0.000000f}, {0.015765f, 0.000000f, 0.000000f},
{0.015152f, 0.000000f, 0.000000f}, {0.014275f, 0.000000f, 0.000000f},
{0.013667f, 0.000000f, 0.000000f}, {0.012905f, 0.000000f, 0.000000f},
{0.012515f, 0.000000f, 0.000000f}, {0.012135f, 0.000000f, 0.000000f},
{0.011499f, 0.000000f, 0.000000f}, {0.010930f, 0.000000f, 0.000000f},
{0.010361f, 0.000000f, 0.000000f}, {0.009792f, 0.000000f, 0.000000f},
{0.009257f, 0.000000f, 0.000000f}, {0.008541f, 0.000000f, 0.000000f},
{0.008039f, 0.000000f, 0.000000f}, {0.007511f, 0.000000f, 0.000000f},
{0.007045f, 0.000000f, 0.000000f}, {0.006428f, 0.000000f, 0.000000f},
{0.005688f, 0.000000f, 0.000000f}, {0.005073f, 0.000000f, 0.000000f},
{0.004643f, 0.000000f, 0.000000f}, {0.004030f, 0.000000f, 0.000000f},
{0.003692f, 0.000000f, 0.000000f}, {0.003418f, 0.000000f, 0.000000f},
{0.002779f, 0.000000f, 0.000000f}, {0.002202f, 0.000000f, 0.000000f},
{0.001355f, 0.000000f, 0.000000f}, {0.000631f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f}};
const float cycles_random_walk_reference_sss_profile[256][3] = {
{0.998589f, 0.998557f, 0.998620f}, {0.915669f, 0.707256f, 0.558430f},
{0.850023f, 0.556568f, 0.395164f}, {0.794334f, 0.460739f, 0.304475f},
{0.746514f, 0.392311f, 0.248659f}, {0.704975f, 0.341595f, 0.211408f},
{0.669223f, 0.302535f, 0.183040f}, {0.636678f, 0.272048f, 0.161929f},
{0.605708f, 0.247362f, 0.145065f}, {0.579075f, 0.226898f, 0.130431f},
{0.554892f, 0.209521f, 0.118052f}, {0.531778f, 0.194031f, 0.108264f},
{0.511444f, 0.181311f, 0.099382f}, {0.492432f, 0.170533f, 0.091852f},
{0.474961f, 0.160716f, 0.083810f}, {0.458917f, 0.151794f, 0.076523f},
{0.443574f, 0.143627f, 0.068829f}, {0.429108f, 0.136497f, 0.062427f},
{0.415735f, 0.129236f, 0.056356f}, {0.403294f, 0.123633f, 0.050555f},
{0.391345f, 0.117985f, 0.045086f}, {0.380587f, 0.112950f, 0.040050f},
{0.370766f, 0.108091f, 0.035180f}, {0.360591f, 0.103149f, 0.030221f},
{0.351328f, 0.098884f, 0.026461f}, {0.342819f, 0.094375f, 0.023097f},
{0.334290f, 0.090286f, 0.019406f}, {0.326302f, 0.086282f, 0.016382f},
{0.318789f, 0.082196f, 0.013610f}, {0.311554f, 0.078111f, 0.011696f},
{0.304418f, 0.074763f, 0.009818f}, {0.297789f, 0.071177f, 0.008059f},
{0.291398f, 0.067713f, 0.006669f}, {0.284717f, 0.064418f, 0.005455f},
{0.279107f, 0.060826f, 0.004499f}, {0.273939f, 0.057600f, 0.003608f},
{0.268261f, 0.054409f, 0.002991f}, {0.263058f, 0.051668f, 0.002612f},
{0.258612f, 0.049441f, 0.002191f}, {0.253361f, 0.046681f, 0.001783f},
{0.248583f, 0.043406f, 0.001415f}, {0.244151f, 0.040832f, 0.001145f},
{0.239688f, 0.038572f, 0.000965f}, {0.235360f, 0.036236f, 0.000771f},
{0.231062f, 0.033796f, 0.000604f}, {0.226948f, 0.031833f, 0.000483f},
{0.222936f, 0.029632f, 0.000377f}, {0.219348f, 0.027854f, 0.000371f},
{0.216285f, 0.025880f, 0.000210f}, {0.212846f, 0.024203f, 0.000165f},
{0.209798f, 0.022357f, 0.000121f}, {0.207216f, 0.020772f, 0.000144f},
{0.204138f, 0.018929f, 0.000091f}, {0.201391f, 0.017868f, 0.000076f},
{0.198583f, 0.016490f, 0.000046f}, {0.195519f, 0.015242f, 0.000016f},
{0.192952f, 0.014055f, 0.000016f}, {0.190503f, 0.012530f, 0.000054f},
{0.187560f, 0.011652f, 0.000016f}, {0.184811f, 0.010695f, 0.000038f},
{0.181494f, 0.009551f, 0.000038f}, {0.178895f, 0.008694f, 0.000038f},
{0.176584f, 0.007979f, 0.000000f}, {0.174711f, 0.007353f, 0.000038f},
{0.172580f, 0.006561f, 0.000000f}, {0.170692f, 0.005895f, 0.000000f},
{0.168351f, 0.005279f, 0.000000f}, {0.165891f, 0.004679f, 0.000038f},
{0.163747f, 0.004216f, 0.000038f}, {0.161710f, 0.003726f, 0.000000f},
{0.159570f, 0.003386f, 0.000038f}, {0.157822f, 0.002994f, 0.000038f},
{0.156176f, 0.002691f, 0.000038f}, {0.154411f, 0.002341f, 0.000038f},
{0.152678f, 0.002006f, 0.000038f}, {0.151122f, 0.001923f, 0.000000f},
{0.148831f, 0.001732f, 0.000038f}, {0.147277f, 0.001573f, 0.000000f},
{0.146147f, 0.001413f, 0.000038f}, {0.144642f, 0.001278f, 0.000038f},
{0.143287f, 0.001218f, 0.000038f}, {0.141765f, 0.001091f, 0.000000f},
{0.140889f, 0.000953f, 0.000000f}, {0.139290f, 0.000756f, 0.000000f},
{0.138189f, 0.000688f, 0.000038f}, {0.136729f, 0.000580f, 0.000038f},
{0.135104f, 0.000450f, 0.000000f}, {0.133794f, 0.000412f, 0.000038f},
{0.132695f, 0.000349f, 0.000038f}, {0.131162f, 0.000296f, 0.000000f},
{0.129554f, 0.000303f, 0.000038f}, {0.128187f, 0.000234f, 0.000000f},
{0.126865f, 0.000209f, 0.000038f}, {0.125874f, 0.000188f, 0.000000f},
{0.124408f, 0.000194f, 0.000038f}, {0.123253f, 0.000157f, 0.000000f},
{0.122158f, 0.000141f, 0.000000f}, {0.120646f, 0.000141f, 0.000000f},
{0.119765f, 0.000048f, 0.000000f}, {0.118912f, 0.000054f, 0.000038f},
{0.117264f, 0.000022f, 0.000038f}, {0.116459f, 0.000016f, 0.000000f},
{0.115503f, 0.000016f, 0.000000f}, {0.114394f, 0.000000f, 0.000000f},
{0.113467f, 0.000000f, 0.000000f}, {0.112297f, 0.000006f, 0.000039f},
{0.111491f, 0.000000f, 0.000000f}, {0.110609f, 0.000006f, 0.000039f},
{0.109727f, 0.000000f, 0.000000f}, {0.108768f, 0.000000f, 0.000000f},
{0.107718f, 0.000000f, 0.000000f}, {0.106835f, 0.000006f, 0.000039f},
{0.105800f, 0.000000f, 0.000000f}, {0.104871f, 0.000000f, 0.000000f},
{0.103805f, 0.000006f, 0.000039f}, {0.102997f, 0.000000f, 0.000000f},
{0.101992f, 0.000000f, 0.000000f}, {0.101124f, 0.000006f, 0.000039f},
{0.100254f, 0.000000f, 0.000000f}, {0.099369f, 0.000006f, 0.000039f},
{0.098484f, 0.000006f, 0.000039f}, {0.097720f, 0.000000f, 0.000000f},
{0.096804f, 0.000000f, 0.000000f}, {0.095767f, 0.000006f, 0.000039f},
{0.095003f, 0.000000f, 0.000000f}, {0.094072f, 0.000000f, 0.000000f},
{0.093048f, 0.000000f, 0.000000f}, {0.092329f, 0.000000f, 0.000000f},
{0.091458f, 0.000006f, 0.000039f}, {0.090677f, 0.000006f, 0.000039f},
{0.090049f, 0.000006f, 0.000039f}, {0.089344f, 0.000006f, 0.000039f},
{0.088503f, 0.000006f, 0.000039f}, {0.087950f, 0.000000f, 0.000000f},
{0.087260f, 0.000006f, 0.000039f}, {0.086524f, 0.000006f, 0.000039f},
{0.085636f, 0.000006f, 0.000039f}, {0.084870f, 0.000000f, 0.000000f},
{0.084073f, 0.000006f, 0.000039f}, {0.083352f, 0.000006f, 0.000039f},
{0.082401f, 0.000006f, 0.000039f}, {0.081512f, 0.000006f, 0.000039f},
{0.080668f, 0.000000f, 0.000000f}, {0.079687f, 0.000000f, 0.000000f},
{0.078935f, 0.000000f, 0.000000f}, {0.078273f, 0.000000f, 0.000000f},
{0.077718f, 0.000006f, 0.000039f}, {0.077240f, 0.000006f, 0.000039f},
{0.076486f, 0.000006f, 0.000039f}, {0.075596f, 0.000006f, 0.000039f},
{0.074949f, 0.000006f, 0.000039f}, {0.074179f, 0.000006f, 0.000039f},
{0.073349f, 0.000000f, 0.000000f}, {0.072625f, 0.000006f, 0.000039f},
{0.071978f, 0.000000f, 0.000000f}, {0.071177f, 0.000000f, 0.000000f},
{0.070499f, 0.000000f, 0.000000f}, {0.069774f, 0.000000f, 0.000000f},
{0.069156f, 0.000006f, 0.000039f}, {0.068493f, 0.000000f, 0.000000f},
{0.068012f, 0.000000f, 0.000000f}, {0.067303f, 0.000006f, 0.000039f},
{0.066547f, 0.000000f, 0.000000f}, {0.065745f, 0.000000f, 0.000000f},
{0.065097f, 0.000006f, 0.000039f}, {0.064371f, 0.000000f, 0.000000f},
{0.063813f, 0.000000f, 0.000000f}, {0.063179f, 0.000006f, 0.000039f},
{0.062346f, 0.000006f, 0.000039f}, {0.061636f, 0.000006f, 0.000039f},
{0.060970f, 0.000000f, 0.000000f}, {0.060244f, 0.000006f, 0.000039f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f}};
#endif
} // namespace blender::eevee::lut

View File

@ -26,5 +26,16 @@ extern const float bsdf_ggx[16][64][64][3];
extern const float btdf_ggx[16][64][64][1];
/* 4 different blue noise, one per channel. */
extern const float blue_noise[64][64][4];
/* Precomputed translucency profile of a slab of material with varying thickness. */
extern const float burley_sss_profile[64][1];
/* Precomputed translucency profile of a slab of material with varying thickness. */
extern const float random_walk_sss_profile[64][1];
#ifdef CYCLES_REFERENCE_LUT
/* Precomputed translucency profile of a slab of material with varying thickness. */
extern const float cycles_burley_reference_sss_profile[256][3];
/* Precomputed translucency profile of a slab of material with varying thickness. */
extern const float cycles_random_walk_reference_sss_profile[256][3];
#endif
} // namespace blender::eevee::lut

View File

@ -392,6 +392,7 @@ void DeferredLayer::begin_sync()
/* G-buffer. */
gbuffer_ps_.bind_image(GBUF_CLOSURE_SLOT, &inst_.gbuffer.closure_tx);
gbuffer_ps_.bind_image(GBUF_COLOR_SLOT, &inst_.gbuffer.color_tx);
gbuffer_ps_.bind_image(GBUF_HEADER_SLOT, &inst_.gbuffer.header_tx);
/* RenderPasses & AOVs. */
gbuffer_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
gbuffer_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
@ -424,35 +425,48 @@ void DeferredLayer::end_sync()
{
eClosureBits evaluated_closures = CLOSURE_DIFFUSE | CLOSURE_REFLECTION | CLOSURE_REFRACTION;
if (closure_bits_ & evaluated_closures) {
const bool is_last_eval_pass = !(closure_bits_ & CLOSURE_SSS);
eval_light_ps_.init();
/* Use stencil test to reject pixel not written by this layer. */
eval_light_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL |
DRW_STATE_BLEND_CUSTOM);
eval_light_ps_.state_stencil(0x00u, 0x00u, evaluated_closures);
eval_light_ps_.shader_set(inst_.shaders.static_shader_get(DEFERRED_LIGHT));
eval_light_ps_.bind_image("out_diffuse_light_img", &diffuse_light_tx_);
eval_light_ps_.bind_image("out_specular_light_img", &specular_light_tx_);
eval_light_ps_.bind_image("indirect_refraction_img", &indirect_refraction_tx_);
eval_light_ps_.bind_image("indirect_reflection_img", &indirect_reflection_tx_);
eval_light_ps_.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
eval_light_ps_.bind_texture("gbuffer_color_tx", &inst_.gbuffer.color_tx);
eval_light_ps_.push_constant("is_last_eval_pass", is_last_eval_pass);
eval_light_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
eval_light_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
eval_light_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
inst_.bind_uniform_data(&eval_light_ps_);
inst_.lights.bind_resources(&eval_light_ps_);
inst_.shadows.bind_resources(&eval_light_ps_);
inst_.sampling.bind_resources(&eval_light_ps_);
inst_.hiz_buffer.bind_resources(&eval_light_ps_);
inst_.reflection_probes.bind_resources(&eval_light_ps_);
inst_.irradiance_cache.bind_resources(&eval_light_ps_);
eval_light_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
eval_light_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
{
PassSimple &pass = eval_light_ps_;
pass.init();
/* Use stencil test to reject pixel not written by this layer. */
pass.state_set(DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
pass.state_stencil(0x00u, 0x00u, evaluated_closures);
pass.shader_set(inst_.shaders.static_shader_get(DEFERRED_LIGHT));
pass.bind_image("direct_diffuse_img", &direct_diffuse_tx_);
pass.bind_image("direct_reflect_img", &direct_reflect_tx_);
pass.bind_image("direct_refract_img", &direct_refract_tx_);
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
pass.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
pass.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
inst_.bind_uniform_data(&pass);
inst_.gbuffer.bind_resources(&pass);
inst_.lights.bind_resources(&pass);
inst_.shadows.bind_resources(&pass);
inst_.sampling.bind_resources(&pass);
inst_.hiz_buffer.bind_resources(&pass);
pass.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
{
PassSimple &pass = combine_ps_;
pass.init();
/* Use stencil test to reject pixel not written by this layer. */
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_BLEND_ADD_FULL);
pass.state_stencil(0x00u, 0x00u, evaluated_closures);
pass.shader_set(inst_.shaders.static_shader_get(DEFERRED_COMBINE));
pass.bind_image("direct_diffuse_img", &direct_diffuse_tx_);
pass.bind_image("direct_reflect_img", &direct_reflect_tx_);
pass.bind_image("direct_refract_img", &direct_refract_tx_);
pass.bind_image("indirect_diffuse_img", &indirect_diffuse_tx_);
pass.bind_image("indirect_reflect_img", &indirect_reflect_tx_);
pass.bind_image("indirect_refract_img", &indirect_refract_tx_);
pass.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
pass.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
inst_.gbuffer.bind_resources(&pass);
inst_.bind_uniform_data(&pass);
pass.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
}
}
@ -541,6 +555,9 @@ void DeferredLayer::render(View &main_view,
}
}
/* TODO(fclem): Clear in pass when Gbuffer will render with framebuffer. */
inst_.gbuffer.header_tx.clear(uint4(0));
GPU_framebuffer_bind(combined_fb);
inst_.manager->submit(gbuffer_ps_, render_view);
@ -556,11 +573,34 @@ void DeferredLayer::render(View &main_view,
main_view,
render_view,
!do_screen_space_refraction);
indirect_refraction_tx_ = refract_result.get();
/* Only update the HiZ after refraction tracing. */
inst_.hiz_buffer.update();
inst_.shadows.set_view(render_view);
{
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE |
GPU_TEXTURE_USAGE_ATTACHMENT;
direct_diffuse_tx_.acquire(extent, GPU_RGBA16F, usage);
direct_reflect_tx_.acquire(extent, GPU_RGBA16F, usage);
direct_refract_tx_.acquire(extent, GPU_RGBA16F, usage);
}
inst_.manager->submit(eval_light_ps_, render_view);
if (closure_bits_ & CLOSURE_SSS) {
inst_.subsurface.render(render_view, combined_fb, direct_diffuse_tx_);
}
RayTraceResult diffuse_result = inst_.raytracing.trace(rt_buffer,
radiance_feedback_tx_,
radiance_feedback_persmat_,
closure_bits_,
CLOSURE_DIFFUSE,
main_view,
render_view);
RayTraceResult reflect_result = inst_.raytracing.trace(rt_buffer,
radiance_feedback_tx_,
radiance_feedback_persmat_,
@ -568,36 +608,27 @@ void DeferredLayer::render(View &main_view,
CLOSURE_REFLECTION,
main_view,
render_view);
indirect_reflection_tx_ = reflect_result.get();
{
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE |
GPU_TEXTURE_USAGE_ATTACHMENT;
diffuse_light_tx_.acquire(extent, GPU_RGBA16F, usage);
diffuse_light_tx_.clear(float4(0.0f));
specular_light_tx_.acquire(extent, GPU_RGBA16F, usage);
specular_light_tx_.clear(float4(0.0f));
}
indirect_diffuse_tx_ = diffuse_result.get();
indirect_reflect_tx_ = reflect_result.get();
indirect_refract_tx_ = refract_result.get();
inst_.shadows.set_view(render_view);
inst_.manager->submit(eval_light_ps_, render_view);
GPU_framebuffer_bind(combined_fb);
inst_.manager->submit(combine_ps_);
diffuse_result.release();
refract_result.release();
reflect_result.release();
if (closure_bits_ & CLOSURE_SSS) {
inst_.subsurface.render(render_view, combined_fb, diffuse_light_tx_);
}
direct_diffuse_tx_.release();
direct_reflect_tx_.release();
direct_refract_tx_.release();
if (do_screen_space_reflection) {
GPU_texture_copy(radiance_feedback_tx_, rb.combined_tx);
radiance_feedback_persmat_ = render_view.persmat();
}
diffuse_light_tx_.release();
specular_light_tx_.release();
inst_.gbuffer.release();
}
@ -728,6 +759,7 @@ void DeferredProbeLayer::begin_sync()
/* G-buffer. */
gbuffer_ps_.bind_image(GBUF_CLOSURE_SLOT, &inst_.gbuffer.closure_tx);
gbuffer_ps_.bind_image(GBUF_COLOR_SLOT, &inst_.gbuffer.color_tx);
gbuffer_ps_.bind_image(GBUF_HEADER_SLOT, &inst_.gbuffer.header_tx);
/* RenderPasses & AOVs. */
gbuffer_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
gbuffer_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
@ -763,35 +795,25 @@ void DeferredProbeLayer::begin_sync()
void DeferredProbeLayer::end_sync()
{
if (closure_bits_ & (CLOSURE_DIFFUSE | CLOSURE_REFLECTION)) {
const bool is_last_eval_pass = !(closure_bits_ & CLOSURE_SSS);
eval_light_ps_.init();
PassSimple &pass = eval_light_ps_;
pass.init();
/* Use stencil test to reject pixel not written by this layer. */
eval_light_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL |
DRW_STATE_BLEND_CUSTOM);
eval_light_ps_.state_stencil(0x00u, 0x00u, (CLOSURE_DIFFUSE | CLOSURE_REFLECTION));
eval_light_ps_.shader_set(inst_.shaders.static_shader_get(DEFERRED_LIGHT_DIFFUSE_ONLY));
eval_light_ps_.bind_image("out_diffuse_light_img", dummy_light_tx_);
eval_light_ps_.bind_image("out_specular_light_img", dummy_light_tx_);
eval_light_ps_.bind_image("indirect_refraction_img", dummy_light_tx_);
eval_light_ps_.bind_image("indirect_reflection_img", dummy_light_tx_);
eval_light_ps_.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
eval_light_ps_.bind_texture("gbuffer_color_tx", &inst_.gbuffer.color_tx);
eval_light_ps_.push_constant("is_last_eval_pass", is_last_eval_pass);
eval_light_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
eval_light_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
eval_light_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
inst_.bind_uniform_data(&eval_light_ps_);
inst_.lights.bind_resources(&eval_light_ps_);
inst_.shadows.bind_resources(&eval_light_ps_);
inst_.sampling.bind_resources(&eval_light_ps_);
inst_.hiz_buffer.bind_resources(&eval_light_ps_);
inst_.reflection_probes.bind_resources(&eval_light_ps_);
inst_.irradiance_cache.bind_resources(&eval_light_ps_);
eval_light_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
eval_light_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL);
pass.state_stencil(0x00u, 0x00u, (CLOSURE_DIFFUSE | CLOSURE_REFLECTION));
pass.shader_set(inst_.shaders.static_shader_get(DEFERRED_CAPTURE_EVAL));
pass.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
pass.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
inst_.bind_uniform_data(&pass);
inst_.gbuffer.bind_resources(&pass);
inst_.lights.bind_resources(&pass);
inst_.shadows.bind_resources(&pass);
inst_.sampling.bind_resources(&pass);
inst_.hiz_buffer.bind_resources(&pass);
inst_.reflection_probes.bind_resources(&pass);
inst_.irradiance_cache.bind_resources(&pass);
pass.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
}

View File

@ -180,7 +180,10 @@ class DeferredLayer {
PassMain::Sub *gbuffer_single_sided_ps_ = nullptr;
PassMain::Sub *gbuffer_double_sided_ps_ = nullptr;
/* Evaluate all light objects contribution. */
PassSimple eval_light_ps_ = {"EvalLights"};
/* Combine direct and indirect light contributions and apply BSDF color. */
PassSimple combine_ps_ = {"Combine"};
/* Closures bits from the materials in this pass. */
eClosureBits closure_bits_ = CLOSURE_NONE;
@ -193,17 +196,18 @@ class DeferredLayer {
*
* NOTE: Not to be confused with the render passes.
*/
TextureFromPool diffuse_light_tx_ = {"diffuse_light_accum_tx"};
TextureFromPool specular_light_tx_ = {"specular_light_accum_tx"};
TextureFromPool direct_diffuse_tx_ = {"direct_diffuse_tx"};
TextureFromPool direct_reflect_tx_ = {"direct_reflect_tx"};
TextureFromPool direct_refract_tx_ = {"direct_refract_tx"};
/* Reference to ray-tracing result. */
GPUTexture *indirect_diffuse_tx_ = nullptr;
GPUTexture *indirect_reflect_tx_ = nullptr;
GPUTexture *indirect_refract_tx_ = nullptr;
Texture radiance_behind_tx_ = {"radiance_behind_tx"};
Texture radiance_feedback_tx_ = {"radiance_feedback_tx"};
float4x4 radiance_feedback_persmat_;
/* Reference to ray-tracing result. */
GPUTexture *indirect_refraction_tx_ = nullptr;
GPUTexture *indirect_reflection_tx_ = nullptr;
public:
DeferredLayer(Instance &inst) : inst_(inst){};
@ -378,15 +382,16 @@ class UtilityTexture : public Texture {
}
{
Layer &layer = data[UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER];
const Vector<float> &transmittance_profile = SubsurfaceModule::transmittance_profile();
BLI_assert(transmittance_profile.size() == lut_size);
/* Repeatedly stored on every row for correct interpolation. */
for (auto y : IndexRange(lut_size)) {
for (auto x : IndexRange(lut_size)) {
/* Only the first channel is used. */
layer.data[y][x] = float4(transmittance_profile[x]);
/* Repeatedly stored on every row for correct interpolation. */
layer.data[y][x][0] = lut::burley_sss_profile[x][0];
layer.data[y][x][1] = lut::random_walk_sss_profile[x][0];
layer.data[y][x][2] = 0.0f;
layer.data[y][x][UTIL_DISK_INTEGRAL_COMP] = lut::ltc_disk_integral[y][x][0];
}
}
BLI_assert(UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER == UTIL_DISK_INTEGRAL_LAYER);
}
{
Layer &layer = data[UTIL_LTC_MAT_LAYER];
@ -404,14 +409,6 @@ class UtilityTexture : public Texture {
}
BLI_assert(UTIL_LTC_MAG_LAYER == UTIL_BSDF_LAYER);
}
{
Layer &layer = data[UTIL_DISK_INTEGRAL_LAYER];
for (auto x : IndexRange(lut_size)) {
for (auto y : IndexRange(lut_size)) {
layer.data[y][x][UTIL_DISK_INTEGRAL_COMP] = lut::ltc_disk_integral[y][x][0];
}
}
}
{
for (auto layer_id : IndexRange(16)) {
Layer &layer = data[UTIL_BTDF_LAYER + layer_id];

View File

@ -105,7 +105,7 @@ class Precompute {
std::ofstream file;
file.open(std::string(name) + ".hh");
file << "const VecBase<float, " << VecT::type_length << "> " << name;
file << "const float " << name;
if (n_w > 1) {
file << "[" << n_w << "]";
}
@ -118,6 +118,7 @@ class Precompute {
if (n_x > 1) {
file << "[" << n_x << "]";
}
file << "[" << VecT::type_length << "]";
file << " = {\n";
/* Print data formatted as C++ array. */
for (auto w : IndexRange(n_w)) {

View File

@ -41,17 +41,26 @@ void RayTraceModule::sync()
{
Texture &depth_tx = inst_.render_buffers.depth_tx;
#define SHADER_VARIATION(_shader_name, _index) \
((_index == 0) ? _shader_name##REFLECT : \
(_index == 1) ? _shader_name##REFRACT : \
_shader_name##DIFFUSE)
#define PASS_VARIATION(_pass_name, _index, _suffix) \
((_index == 0) ? _pass_name##reflect##_suffix : \
(_index == 1) ? _pass_name##refract##_suffix : \
_pass_name##diffuse##_suffix)
/* Setup. */
{
PassSimple &pass = tile_classify_ps_;
pass.init();
pass.shader_set(inst_.shaders.static_shader_get(RAY_TILE_CLASSIFY));
pass.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
pass.bind_texture("stencil_tx", &renderbuf_stencil_view_);
pass.bind_image("tile_mask_img", &tile_mask_tx_);
pass.bind_ssbo("ray_dispatch_buf", &ray_dispatch_buf_);
pass.bind_ssbo("denoise_dispatch_buf", &denoise_dispatch_buf_);
inst_.bind_uniform_data(&pass);
inst_.gbuffer.bind_resources(&pass);
pass.dispatch(&tile_classify_dispatch_size_);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_SHADER_STORAGE);
}
@ -68,28 +77,24 @@ void RayTraceModule::sync()
pass.dispatch(&tile_compact_dispatch_size_);
pass.barrier(GPU_BARRIER_SHADER_STORAGE);
}
for (auto type : IndexRange(2)) {
PassSimple &pass = (type == 0) ? generate_reflect_ps_ : generate_refract_ps_;
for (auto type : IndexRange(3)) {
PassSimple &pass = PASS_VARIATION(generate_, type, _ps_);
pass.init();
pass.shader_set(inst_.shaders.static_shader_get((type == 0) ? RAY_GENERATE_REFLECT :
RAY_GENERATE_REFRACT));
pass.shader_set(inst_.shaders.static_shader_get(SHADER_VARIATION(RAY_GENERATE_, type)));
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
pass.bind_texture("stencil_tx", &renderbuf_stencil_view_);
pass.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
pass.bind_texture("gbuffer_color_tx", &inst_.gbuffer.color_tx);
pass.bind_image("out_ray_data_img", &ray_data_tx_);
pass.bind_ssbo("tiles_coord_buf", &ray_tiles_buf_);
inst_.sampling.bind_resources(&pass);
inst_.gbuffer.bind_resources(&pass);
pass.dispatch(ray_dispatch_buf_);
pass.barrier(GPU_BARRIER_SHADER_STORAGE | GPU_BARRIER_TEXTURE_FETCH |
GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
/* Tracing. */
for (auto type : IndexRange(2)) {
PassSimple &pass = (type == 0) ? trace_reflect_ps_ : trace_refract_ps_;
for (auto type : IndexRange(3)) {
PassSimple &pass = PASS_VARIATION(trace_, type, _ps_);
pass.init();
pass.shader_set(inst_.shaders.static_shader_get((type == 0) ? RAY_TRACE_SCREEN_REFLECT :
RAY_TRACE_SCREEN_REFRACT));
pass.shader_set(inst_.shaders.static_shader_get(SHADER_VARIATION(RAY_TRACE_SCREEN_, type)));
pass.bind_ssbo("tiles_coord_buf", &ray_tiles_buf_);
pass.bind_image("ray_data_img", &ray_data_tx_);
pass.bind_image("ray_time_img", &ray_time_tx_);
@ -118,15 +123,12 @@ void RayTraceModule::sync()
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
/* Denoise. */
for (auto type : IndexRange(2)) {
PassSimple &pass = (type == 0) ? denoise_spatial_reflect_ps_ : denoise_spatial_refract_ps_;
for (auto type : IndexRange(3)) {
PassSimple &pass = PASS_VARIATION(denoise_spatial_, type, _ps_);
pass.init();
pass.shader_set(inst_.shaders.static_shader_get((type == 0) ? RAY_DENOISE_SPATIAL_REFLECT :
RAY_DENOISE_SPATIAL_REFRACT));
pass.shader_set(inst_.shaders.static_shader_get(SHADER_VARIATION(RAY_DENOISE_SPATIAL_, type)));
pass.bind_ssbo("tiles_coord_buf", &denoise_tiles_buf_);
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
pass.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
pass.bind_texture("stencil_tx", &renderbuf_stencil_view_);
pass.bind_texture("depth_tx", &depth_tx);
pass.bind_image("ray_data_img", &ray_data_tx_);
pass.bind_image("ray_time_img", &ray_time_tx_);
@ -137,6 +139,7 @@ void RayTraceModule::sync()
pass.bind_image("tile_mask_img", &tile_mask_tx_);
inst_.bind_uniform_data(&pass);
inst_.sampling.bind_resources(&pass);
inst_.gbuffer.bind_resources(&pass);
pass.dispatch(denoise_dispatch_buf_);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
@ -159,12 +162,11 @@ void RayTraceModule::sync()
pass.dispatch(denoise_dispatch_buf_);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
for (auto type : IndexRange(2)) {
PassSimple &pass = (type == 0) ? denoise_bilateral_reflect_ps_ : denoise_bilateral_refract_ps_;
for (auto type : IndexRange(3)) {
PassSimple &pass = PASS_VARIATION(denoise_bilateral_, type, _ps_);
pass.init();
pass.shader_set(inst_.shaders.static_shader_get((type == 0) ? RAY_DENOISE_BILATERAL_REFLECT :
RAY_DENOISE_BILATERAL_REFRACT));
pass.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
pass.shader_set(
inst_.shaders.static_shader_get(SHADER_VARIATION(RAY_DENOISE_BILATERAL_, type)));
pass.bind_texture("depth_tx", &depth_tx);
pass.bind_image("in_radiance_img", &denoised_temporal_tx_);
pass.bind_image("out_radiance_img", &denoised_bilateral_tx_);
@ -173,9 +175,13 @@ void RayTraceModule::sync()
pass.bind_ssbo("tiles_coord_buf", &denoise_tiles_buf_);
inst_.bind_uniform_data(&pass);
inst_.sampling.bind_resources(&pass);
inst_.gbuffer.bind_resources(&pass);
pass.dispatch(denoise_dispatch_buf_);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
#undef SHADER_VARIATION
#undef PASS_VARIATION
}
void RayTraceModule::debug_pass_sync() {}
@ -194,8 +200,8 @@ RayTraceResult RayTraceModule::trace(RayTraceBuffer &rt_buffer,
{
BLI_assert_msg(count_bits_i(raytrace_closure) == 1,
"Only one closure type can be raytraced at a time.");
BLI_assert_msg(raytrace_closure ==
(raytrace_closure & (CLOSURE_REFLECTION | CLOSURE_REFRACTION)),
BLI_assert_msg(raytrace_closure == (raytrace_closure &
(CLOSURE_REFLECTION | CLOSURE_REFRACTION | CLOSURE_DIFFUSE)),
"Only reflection and refraction are implemented.");
if (tracing_method_ == RAYTRACE_EEVEE_METHOD_NONE) {
@ -211,7 +217,15 @@ RayTraceResult RayTraceModule::trace(RayTraceBuffer &rt_buffer,
PassSimple *denoise_bilateral_ps = nullptr;
RayTraceBuffer::DenoiseBuffer *denoise_buf = nullptr;
if (raytrace_closure == CLOSURE_REFLECTION) {
if (raytrace_closure == CLOSURE_DIFFUSE) {
options = reflection_options_;
generate_ray_ps = &generate_diffuse_ps_;
trace_ray_ps = force_no_tracing ? &trace_diffuse_ps_ : &trace_diffuse_ps_;
denoise_spatial_ps = &denoise_spatial_diffuse_ps_;
denoise_bilateral_ps = &denoise_bilateral_diffuse_ps_;
denoise_buf = &rt_buffer.diffuse;
}
else if (raytrace_closure == CLOSURE_REFLECTION) {
options = reflection_options_;
generate_ray_ps = &generate_reflect_ps_;
trace_ray_ps = force_no_tracing ? &trace_fallback_ps_ : &trace_reflect_ps_;
@ -290,7 +304,7 @@ RayTraceResult RayTraceModule::trace(RayTraceBuffer &rt_buffer,
{
/* Tracing rays. */
ray_data_tx_.acquire(tracing_res, GPU_RGBA16F);
ray_time_tx_.acquire(tracing_res, GPU_R32F);
ray_time_tx_.acquire(tracing_res, RAYTRACE_RAYTIME_FORMAT);
ray_radiance_tx_.acquire(tracing_res, RAYTRACE_RADIANCE_FORMAT);
inst_.manager->submit(*generate_ray_ps, render_view);

View File

@ -54,7 +54,7 @@ struct RayTraceBuffer {
* One for each closure type. Not to be mistaken with deferred layer type.
* For instance the opaque deferred layer will only used the reflection history buffer.
*/
DenoiseBuffer reflection, refraction;
DenoiseBuffer reflection, refraction, diffuse;
};
/**
@ -103,14 +103,18 @@ class RayTraceModule {
draw::PassSimple tile_classify_ps_ = {"TileClassify"};
draw::PassSimple tile_compact_ps_ = {"TileCompact"};
draw::PassSimple generate_diffuse_ps_ = {"RayGenerate.Diffuse"};
draw::PassSimple generate_reflect_ps_ = {"RayGenerate.Reflection"};
draw::PassSimple generate_refract_ps_ = {"RayGenerate.Refraction"};
draw::PassSimple trace_diffuse_ps_ = {"Trace.Diffuse"};
draw::PassSimple trace_reflect_ps_ = {"Trace.Reflection"};
draw::PassSimple trace_refract_ps_ = {"Trace.Refraction"};
draw::PassSimple trace_fallback_ps_ = {"Trace.Fallback"};
draw::PassSimple denoise_spatial_diffuse_ps_ = {"DenoiseSpatial.Diffuse"};
draw::PassSimple denoise_spatial_reflect_ps_ = {"DenoiseSpatial.Reflection"};
draw::PassSimple denoise_spatial_refract_ps_ = {"DenoiseSpatial.Refraction"};
draw::PassSimple denoise_temporal_ps_ = {"DenoiseTemporal"};
draw::PassSimple denoise_bilateral_diffuse_ps_ = {"DenoiseBilateral.Diffuse"};
draw::PassSimple denoise_bilateral_reflect_ps_ = {"DenoiseBilateral.Reflection"};
draw::PassSimple denoise_bilateral_refract_ps_ = {"DenoiseBilateral.Refraction"};

View File

@ -88,10 +88,12 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
return "eevee_film_comp";
case FILM_CRYPTOMATTE_POST:
return "eevee_film_cryptomatte_post";
case DEFERRED_COMBINE:
return "eevee_deferred_combine";
case DEFERRED_LIGHT:
return "eevee_deferred_light";
case DEFERRED_LIGHT_DIFFUSE_ONLY:
return "eevee_deferred_light_diffuse";
case DEFERRED_CAPTURE_EVAL:
return "eevee_deferred_capture_eval";
case HIZ_DEBUG:
return "eevee_hiz_debug";
case HIZ_UPDATE:
@ -154,22 +156,30 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
return "eevee_light_culling_tile";
case LIGHT_CULLING_ZBIN:
return "eevee_light_culling_zbin";
case RAY_DENOISE_SPATIAL_DIFFUSE:
return "eevee_ray_denoise_spatial_diffuse";
case RAY_DENOISE_SPATIAL_REFLECT:
return "eevee_ray_denoise_spatial_reflect";
case RAY_DENOISE_SPATIAL_REFRACT:
return "eevee_ray_denoise_spatial_refract";
case RAY_DENOISE_TEMPORAL:
return "eevee_ray_denoise_temporal";
case RAY_DENOISE_BILATERAL_DIFFUSE:
return "eevee_ray_denoise_bilateral_diffuse";
case RAY_DENOISE_BILATERAL_REFLECT:
return "eevee_ray_denoise_bilateral_reflect";
case RAY_DENOISE_BILATERAL_REFRACT:
return "eevee_ray_denoise_bilateral_refract";
case RAY_GENERATE_DIFFUSE:
return "eevee_ray_generate_diffuse";
case RAY_GENERATE_REFLECT:
return "eevee_ray_generate_reflect";
case RAY_GENERATE_REFRACT:
return "eevee_ray_generate_refract";
case RAY_TRACE_FALLBACK:
return "eevee_ray_trace_fallback";
case RAY_TRACE_SCREEN_DIFFUSE:
return "eevee_ray_trace_screen_diffuse";
case RAY_TRACE_SCREEN_REFLECT:
return "eevee_ray_trace_screen_reflect";
case RAY_TRACE_SCREEN_REFRACT:

View File

@ -32,8 +32,9 @@ enum eShaderType {
FILM_COMP,
FILM_CRYPTOMATTE_POST,
DEFERRED_COMBINE,
DEFERRED_LIGHT,
DEFERRED_LIGHT_DIFFUSE_ONLY,
DEFERRED_CAPTURE_EVAL,
DEBUG_SURFELS,
DEBUG_IRRADIANCE_GRID,
@ -77,16 +78,20 @@ enum eShaderType {
MOTION_BLUR_TILE_FLATTEN_RGBA,
MOTION_BLUR_TILE_FLATTEN_RG,
RAY_DENOISE_BILATERAL_DIFFUSE,
RAY_DENOISE_BILATERAL_REFLECT,
RAY_DENOISE_BILATERAL_REFRACT,
RAY_DENOISE_SPATIAL_DIFFUSE,
RAY_DENOISE_SPATIAL_REFLECT,
RAY_DENOISE_SPATIAL_REFRACT,
RAY_DENOISE_TEMPORAL,
RAY_GENERATE_DIFFUSE,
RAY_GENERATE_REFLECT,
RAY_GENERATE_REFRACT,
RAY_TILE_CLASSIFY,
RAY_TILE_COMPACT,
RAY_TRACE_FALLBACK,
RAY_TRACE_SCREEN_DIFFUSE,
RAY_TRACE_SCREEN_REFLECT,
RAY_TRACE_SCREEN_REFRACT,

View File

@ -90,6 +90,8 @@ enum PrecomputeType : uint32_t {
LUT_GGX_BRDF_SPLIT_SUM = 0u,
LUT_GGX_BTDF_IOR_GT_ONE = 1u,
LUT_GGX_BSDF_SPLIT_SUM = 2u,
LUT_BURLEY_SSS_PROFILE = 3u,
LUT_RANDOM_WALK_SSS_PROFILE = 4u,
};
/** \} */
@ -1199,7 +1201,7 @@ BLI_STATIC_ASSERT_ALIGN(AOData, 16)
#define SSS_BURLEY_TRUNCATE 16.0
#define SSS_BURLEY_TRUNCATE_CDF 0.9963790093708328
#define SSS_TRANSMIT_LUT_SIZE 64.0
#define SSS_TRANSMIT_LUT_RADIUS 1.218
#define SSS_TRANSMIT_LUT_RADIUS 2.0
#define SSS_TRANSMIT_LUT_SCALE ((SSS_TRANSMIT_LUT_SIZE - 1.0) / float(SSS_TRANSMIT_LUT_SIZE))
#define SSS_TRANSMIT_LUT_BIAS (0.5 / float(SSS_TRANSMIT_LUT_SIZE))
#define SSS_TRANSMIT_LUT_STEP_RES 64.0
@ -1217,6 +1219,37 @@ struct SubsurfaceData {
};
BLI_STATIC_ASSERT_ALIGN(SubsurfaceData, 16)
static inline float3 burley_setup(float3 radius, float3 albedo)
{
/* TODO(fclem): Avoid constant duplication. */
const float m_1_pi = 0.318309886183790671538;
float3 A = albedo;
/* Diffuse surface transmission, equation (6). */
float3 s = 1.9 - A + 3.5 * ((A - 0.8) * (A - 0.8));
/* Mean free path length adapted to fit ancient Cubic and Gaussian models. */
float3 l = 0.25 * m_1_pi * radius;
return l / s;
}
static inline float3 burley_eval(float3 d, float r)
{
/* Slide 33. */
float3 exp_r_3_d;
/* TODO(fclem): Vectorize. */
exp_r_3_d.x = expf(-r / (3.0 * d.x));
exp_r_3_d.y = expf(-r / (3.0 * d.y));
exp_r_3_d.z = expf(-r / (3.0 * d.z));
float3 exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
/* NOTE:
* - Surface albedo is applied at the end.
* - This is normalized diffuse model, so the equation is multiplied
* by 2*pi, which also matches `cdf()`.
*/
return (exp_r_d + exp_r_3_d) / (4.0 * d);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -1294,7 +1327,7 @@ BLI_STATIC_ASSERT_ALIGN(UniformData, 16)
#define UTIL_LTC_MAG_LAYER 3
#define UTIL_BSDF_LAYER 3
#define UTIL_BTDF_LAYER 5
#define UTIL_DISK_INTEGRAL_LAYER 4
#define UTIL_DISK_INTEGRAL_LAYER UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER
#define UTIL_DISK_INTEGRAL_COMP 3
/* __cplusplus is true when compiling with MSL, so include if inside a shader. */

View File

@ -36,9 +36,8 @@ void SubsurfaceModule::end_sync()
subsurface_ps_.shader_set(inst_.shaders.static_shader_get(SUBSURFACE_EVAL));
inst_.bind_uniform_data(&subsurface_ps_);
inst_.hiz_buffer.bind_resources(&subsurface_ps_);
inst_.gbuffer.bind_resources(&subsurface_ps_);
subsurface_ps_.bind_texture("radiance_tx", &diffuse_light_tx_);
subsurface_ps_.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
subsurface_ps_.bind_texture("gbuffer_color_tx", &inst_.gbuffer.color_tx);
subsurface_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
/** NOTE: Not used in the shader, but we bind it to avoid debug warnings. */
subsurface_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
@ -59,7 +58,7 @@ void SubsurfaceModule::render(View &view, Framebuffer &fb, Texture &diffuse_ligh
void SubsurfaceModule::precompute_samples_location()
{
/* Precompute sample position with white albedo. */
float d = burley_setup(1.0f, 1.0f);
float d = burley_setup(float3(1.0f), float3(1.0f)).x;
float rand_u = inst_.sampling.rng_get(SAMPLING_SSS_U);
float rand_v = inst_.sampling.rng_get(SAMPLING_SSS_V);
@ -69,7 +68,7 @@ void SubsurfaceModule::precompute_samples_location()
float theta = golden_angle * i + M_PI * 2.0f * rand_u;
/* Scale using rand_v in order to keep first sample always at center. */
float x = (1.0f + (rand_v / data_.sample_len)) * (i / float(data_.sample_len));
float r = burley_sample(d, x);
float r = SubsurfaceModule::burley_sample(d, x);
data_.samples[i].x = cosf(theta) * r;
data_.samples[i].y = sinf(theta) * r;
data_.samples[i].z = 1.0f / burley_pdf(d, r);
@ -78,65 +77,6 @@ void SubsurfaceModule::precompute_samples_location()
inst_.push_uniform_data();
}
const Vector<float> &SubsurfaceModule::transmittance_profile()
{
static Vector<float> profile;
if (!profile.is_empty()) {
return profile;
}
profile.resize(SSS_TRANSMIT_LUT_SIZE);
/* Precompute sample position with white albedo. */
float radius = 1.0f;
float d = burley_setup(radius, 1.0f);
/* For each distance d we compute the radiance incoming from an hypothetical parallel plane. */
for (auto i : IndexRange(SSS_TRANSMIT_LUT_SIZE)) {
/* Distance from the lit surface plane.
* Compute to a larger maximum distance to have a smoother falloff for all channels. */
float lut_radius = SSS_TRANSMIT_LUT_RADIUS * radius;
float distance = lut_radius * (i + 1e-5f) / profile.size();
/* Compute radius of the footprint on the hypothetical plane. */
float r_fp = sqrtf(square_f(lut_radius) - square_f(distance));
profile[i] = 0.0f;
float area_accum = 0.0f;
for (auto j : IndexRange(SSS_TRANSMIT_LUT_STEP_RES)) {
/* Compute distance to the "shading" point through the medium. */
float r = (r_fp * (j + 0.5f)) / SSS_TRANSMIT_LUT_STEP_RES;
float r_prev = (r_fp * (j + 0.0f)) / SSS_TRANSMIT_LUT_STEP_RES;
float r_next = (r_fp * (j + 1.0f)) / SSS_TRANSMIT_LUT_STEP_RES;
r = hypotf(r, distance);
float R = burley_eval(d, r);
/* Since the profile and configuration are radially symmetrical we
* can just evaluate it once and weight it accordingly */
float disk_area = square_f(r_next) - square_f(r_prev);
profile[i] += R * disk_area;
area_accum += disk_area;
}
/* Normalize over the disk. */
profile[i] /= area_accum;
}
/** NOTE: There's something very wrong here.
* This should be a small remap,
* but current profile range goes from 0.0399098 to 0.0026898. */
/* Make a smooth gradient from 1 to 0. */
float range = profile.first() - profile.last();
float offset = profile.last();
for (float &value : profile) {
value = (value - offset) / range;
/** HACK: Remap the curve to better fit Cycles values. */
value = std::pow(value, 1.6f);
}
profile.first() = 1;
profile.last() = 0;
return profile;
}
/** \} */
/* -------------------------------------------------------------------- */
@ -147,17 +87,6 @@ const Vector<float> &SubsurfaceModule::transmittance_profile()
* https://graphics.pixar.com/library/ApproxBSSRDF/approxbssrdfslides.pdf
* \{ */
float SubsurfaceModule::burley_setup(float radius, float albedo)
{
float A = albedo;
/* Diffuse surface transmission, equation (6). */
float s = 1.9f - A + 3.5f * square_f(A - 0.8f);
/* Mean free path length adapted to fit ancient Cubic and Gaussian models. */
float l = 0.25 * M_1_PI * radius;
return l / s;
}
float SubsurfaceModule::burley_sample(float d, float x_rand)
{
x_rand *= SSS_BURLEY_TRUNCATE_CDF;

View File

@ -49,9 +49,6 @@ struct SubsurfaceModule {
~SubsurfaceModule(){};
/** Contains translucence profile for a single color channel. */
static const Vector<float> &transmittance_profile();
void end_sync();
void render(View &view, Framebuffer &fb, Texture &diffuse_light_tx);
@ -60,7 +57,6 @@ struct SubsurfaceModule {
void precompute_samples_location();
/** Christensen-Burley implementation. */
static float burley_setup(float radius, float albedo);
static float burley_sample(float d, float x_rand);
static float burley_eval(float d, float r);
static float burley_pdf(float d, float r);

View File

@ -173,7 +173,7 @@ vec3 sample_uniform_hemisphere(vec3 rand, vec3 N, vec3 T, vec3 B, out float pdf)
{
vec3 tH = sample_uniform_hemisphere(rand);
pdf = sample_pdf_uniform_hemisphere();
return tH * mat3(N, T, B);
return mat3(T, B, N) * tH;
}
/** \} */
@ -200,7 +200,7 @@ vec3 sample_cosine_hemisphere(vec3 rand, vec3 N, vec3 T, vec3 B, out float pdf)
{
vec3 tH = sample_cosine_hemisphere(rand);
pdf = sample_pdf_cosine_hemisphere(tH.z);
return tH * mat3(N, T, B);
return mat3(T, B, N) * tH;
}
/** \} */

View File

@ -0,0 +1,47 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Compute light objects lighting contribution using captured Gbuffer data.
*/
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_lightprobe_eval_lib.glsl)
void main()
{
ivec2 texel = ivec2(gl_FragCoord.xy);
float depth = texelFetch(hiz_tx, texel, 0).r;
vec3 P = get_world_space_from_depth(uvcoordsvar.xy, depth);
vec3 V = cameraVec(P);
float vP_z = dot(cameraForward, P) - dot(cameraForward, cameraPos);
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel);
vec3 Ng = gbuf.diffuse.N;
vec3 diffuse_light = vec3(0.0);
vec3 unused_reflection_light = vec3(0.0);
vec3 unused_refraction_light = vec3(0.0);
float unused_shadow = 1.0;
light_eval(gbuf.diffuse,
gbuf.reflection,
P,
Ng,
V,
vP_z,
gbuf.thickness,
diffuse_light,
unused_reflection_light,
unused_shadow);
vec3 albedo = gbuf.diffuse.color + gbuf.reflection.color + gbuf.refraction.color;
out_radiance = vec4(diffuse_light * albedo, 0.0);
}

View File

@ -0,0 +1,38 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Combine light passes to the combined color target and apply surface colors.
* This also fills the different render passes.
*/
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_renderpass_lib.glsl)
void main()
{
ivec2 texel = ivec2(gl_FragCoord.xy);
vec3 diffuse_light = imageLoad(direct_diffuse_img, texel).rgb +
imageLoad(indirect_diffuse_img, texel).rgb;
vec3 reflect_light = imageLoad(direct_reflect_img, texel).rgb +
imageLoad(indirect_reflect_img, texel).rgb;
vec3 refract_light = imageLoad(direct_refract_img, texel).rgb +
imageLoad(indirect_refract_img, texel).rgb;
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel);
/* Mask invalid radiance. */
diffuse_light = gbuf.has_diffuse ? diffuse_light : vec3(0.0);
reflect_light = gbuf.has_reflection ? reflect_light : vec3(0.0);
refract_light = gbuf.has_refraction ? refract_light : vec3(0.0);
/* Light passes. */
vec3 specular_light = reflect_light + refract_light;
output_renderpass_color(uniform_buf.render_pass.diffuse_light_id, vec4(diffuse_light, 1.0));
output_renderpass_color(uniform_buf.render_pass.specular_light_id, vec4(specular_light, 1.0));
/* Combine. */
out_combined = vec4(0.0);
out_combined.xyz += diffuse_light * gbuf.diffuse.color;
out_combined.xyz += reflect_light * gbuf.reflection.color;
out_combined.xyz += refract_light * gbuf.refraction.color;
}

View File

@ -5,15 +5,13 @@
/**
* Compute light objects lighting contribution using Gbuffer data.
*
* Output light either directly to the radiance buffers or to temporary radiance accumulation
* buffer that will be processed by other deferred lighting passes.
* Output light .
*/
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_renderpass_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_reflection_probe_eval_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_lightprobe_eval_lib.glsl)
void main()
{
@ -27,99 +25,33 @@ void main()
vec3 V = cameraVec(P);
float vP_z = dot(cameraForward, P) - dot(cameraForward, cameraPos);
vec4 gbuffer_0_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, 0), 0);
vec4 gbuffer_1_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, 1), 0);
ClosureReflection reflection_data;
reflection_data.N = gbuffer_normal_unpack(gbuffer_0_packed.xy);
reflection_data.roughness = gbuffer_0_packed.z;
ClosureDiffuse diffuse_data;
diffuse_data.N = gbuffer_normal_unpack(gbuffer_1_packed.xy);
/* These are only set for SSS case. */
diffuse_data.sss_radius = vec3(0.0);
diffuse_data.sss_id = 0u;
float thickness = 0.0;
ClosureRefraction refraction_data;
refraction_data.N = diffuse_data.N;
refraction_data.roughness = gbuffer_1_packed.z;
refraction_data.ior = 0.0; /* Not needed. */
bool is_refraction = gbuffer_is_refraction(gbuffer_1_packed);
if (is_refraction) {
/* Still evaluate the diffuse light so that dithered SSS / Refraction combination still
* produces a complete diffuse light buffer that will be correctly convolved by the SSSS.
* The refraction pixels will just set the diffuse radiance to 0. */
}
else if (textureSize(gbuffer_closure_tx, 0).z >= 3) {
vec4 gbuffer_2_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, 2), 0);
diffuse_data.sss_radius = gbuffer_sss_radii_unpack(gbuffer_2_packed.xyz);
diffuse_data.sss_id = gbuffer_object_id_unorm16_unpack(gbuffer_2_packed.w);
thickness = gbuffer_thickness_unpack(gbuffer_1_packed.z);
}
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel);
vec3 diffuse_light = vec3(0.0);
#ifdef DO_REFLECTION_PROBES
vec3 reflection_light = imageLoad(indirect_reflection_img, texel).rgb;
vec3 refraction_light = imageLoad(indirect_refraction_img, texel).rgb;
#else
vec3 reflection_light = vec3(0.0);
vec3 refraction_light = vec3(0.0);
#endif
float shadow = 1.0;
lightprobe_eval(diffuse_data, reflection_data, P, Ng, V, diffuse_light, reflection_light);
light_eval(diffuse_data,
reflection_data,
light_eval(gbuf.diffuse,
gbuf.reflection,
P,
Ng,
V,
vP_z,
thickness,
gbuf.thickness,
diffuse_light,
reflection_light,
/* TODO(fclem): Implement refraction light. */
// refraction_light,
shadow);
/* Apply color and output lighting to render-passes. */
vec4 color_0_packed = texelFetch(gbuffer_color_tx, ivec3(texel, 0), 0);
vec4 color_1_packed = texelFetch(gbuffer_color_tx, ivec3(texel, 1), 0);
output_renderpass_value(uniform_buf.render_pass.shadow_id, shadow);
reflection_data.color = gbuffer_color_unpack(color_0_packed);
refraction_data.color = is_refraction ? gbuffer_color_unpack(color_1_packed) : vec3(0.0);
diffuse_data.color = is_refraction ? vec3(0.0) : gbuffer_color_unpack(color_1_packed);
/* Store lighting for next deferred pass. */
/* Output object ID for sub-surface screen space processing. */
float f_sss_id = gbuffer_object_id_f16_pack(gbuf.diffuse.sss_id);
/* Light passes. */
if (uniform_buf.render_pass.diffuse_light_id >= 0) {
imageStore(rp_color_img,
ivec3(texel, uniform_buf.render_pass.diffuse_light_id),
vec4(diffuse_light, 1.0));
}
if (uniform_buf.render_pass.specular_light_id >= 0) {
vec3 specular_light = reflection_light + refraction_light;
imageStore(rp_color_img,
ivec3(texel, uniform_buf.render_pass.specular_light_id),
vec4(specular_light, 1.0));
}
if (uniform_buf.render_pass.shadow_id >= 0) {
imageStore(rp_value_img, ivec3(texel, uniform_buf.render_pass.shadow_id), vec4(shadow));
}
if (!is_last_eval_pass) {
/* Store lighting for next deferred pass. */
vec4 diffuse_radiance;
diffuse_radiance.xyz = diffuse_light;
/* Output object ID for sub-surface screen space processing. */
diffuse_radiance.w = gbuffer_object_id_f16_pack(diffuse_data.sss_id);
imageStore(out_diffuse_light_img, texel, diffuse_radiance);
imageStore(out_specular_light_img, texel, vec4(reflection_light + reflection_light, 0.0));
}
diffuse_light *= diffuse_data.color;
reflection_light *= reflection_data.color;
refraction_light *= refraction_data.color;
/* Add radiance to combined pass. */
out_radiance = vec4(diffuse_light + reflection_light + refraction_light, 0.0);
out_transmittance = vec4(1.0);
imageStore(direct_diffuse_img, texel, vec4(diffuse_light, f_sss_id));
imageStore(direct_reflect_img, texel, vec4(reflection_light, 1.0));
imageStore(direct_refract_img, texel, vec4(refraction_light, 1.0));
}

View File

@ -9,6 +9,8 @@
*/
#pragma BLENDER_REQUIRE(gpu_shader_math_vector_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_codegen_lib.glsl)
vec2 gbuffer_normal_pack(vec3 N)
{
@ -110,3 +112,85 @@ bool gbuffer_is_refraction(vec4 gbuffer)
{
return gbuffer.w < 1.0;
}
struct GBufferData {
ClosureDiffuse diffuse;
ClosureReflection reflection;
ClosureRefraction refraction;
float thickness;
bool has_diffuse;
bool has_reflection;
bool has_refraction;
};
GBufferData gbuffer_read(usampler2D header_tx,
sampler2DArray closure_tx,
sampler2DArray color_tx,
ivec2 texel)
{
GBufferData gbuf;
uint header = texelFetch(header_tx, texel, 0).r;
gbuf.thickness = 0.0;
gbuf.has_diffuse = flag_test(header, CLOSURE_DIFFUSE);
gbuf.has_reflection = flag_test(header, CLOSURE_REFLECTION);
gbuf.has_refraction = flag_test(header, CLOSURE_REFRACTION);
if (gbuf.has_reflection) {
int layer = 0;
vec4 closure_packed = texelFetch(closure_tx, ivec3(texel, layer), 0);
gbuf.reflection.N = gbuffer_normal_unpack(closure_packed.xy);
gbuf.reflection.roughness = closure_packed.z;
vec4 color_packed = texelFetch(color_tx, ivec3(texel, layer), 0);
gbuf.reflection.color = gbuffer_color_unpack(color_packed);
}
else {
gbuf.reflection.N = vec3(0.0, 0.0, 1.0);
gbuf.reflection.roughness = 0.0;
gbuf.reflection.color = vec3(0.0);
}
if (gbuf.has_diffuse) {
int layer = 1;
vec4 closure_packed = texelFetch(closure_tx, ivec3(texel, layer), 0);
gbuf.diffuse.N = gbuffer_normal_unpack(closure_packed.xy);
gbuf.diffuse.sss_id = 0u;
gbuf.thickness = gbuffer_thickness_unpack(closure_packed.z);
vec4 color_packed = texelFetch(color_tx, ivec3(texel, layer), 0);
gbuf.diffuse.color = gbuffer_color_unpack(color_packed);
if (flag_test(header, CLOSURE_SSS)) {
int layer = 2;
vec4 closure_packed = texelFetch(closure_tx, ivec3(texel, layer), 0);
gbuf.diffuse.sss_radius = gbuffer_sss_radii_unpack(closure_packed.xyz);
gbuf.diffuse.sss_id = gbuffer_object_id_unorm16_unpack(closure_packed.w);
}
}
else {
gbuf.diffuse.N = vec3(0.0, 0.0, 1.0);
gbuf.diffuse.sss_id = 0u;
gbuf.diffuse.color = vec3(0.0);
}
if (gbuf.has_refraction) {
int layer = 1;
vec4 closure_packed = texelFetch(closure_tx, ivec3(texel, layer), 0);
gbuf.refraction.N = gbuffer_normal_unpack(closure_packed.xy);
gbuf.refraction.roughness = closure_packed.z;
gbuf.refraction.ior = gbuffer_ior_unpack(closure_packed.w);
vec4 color_packed = texelFetch(color_tx, ivec3(texel, layer), 0);
gbuf.refraction.color = gbuffer_color_unpack(color_packed);
}
else {
gbuf.refraction.N = vec3(0.0, 0.0, 1.0);
gbuf.refraction.ior = 1.1;
gbuf.refraction.roughness = 0.0;
gbuf.refraction.color = vec3(0.0);
}
return gbuf;
}

View File

@ -170,6 +170,53 @@ vec4 ggx_btdf_gt_one(vec3 lut_coord)
return vec4(transmission_factor, 0.0, 0.0, 0.0);
}
/* Generate SSS translucency profile.
* We precompute the exit radiance for a slab of homogenous material backface-lit by a directional
* light. We only integrate for a single color primary since the profile will be applied to each
* primary independantly.
* For each distance `d` we compute the radiance incoming from an hypothetical parallel plane. */
vec4 burley_sss_translucency(vec3 lut_coord)
{
/* Note that we only store the 1st (radius == 1) component.
* The others are here for debugging overall appearance. */
vec3 radii = vec3(1.0, 0.2, 0.1);
float thickness = lut_coord.x * SSS_TRANSMIT_LUT_RADIUS;
vec3 r = thickness / radii;
/* Manual fit based on cycles render of a backlit slab of varying thickness.
* Mean Error: 0.003
* Max Error: 0.015 */
vec3 exponential = exp(-3.6 * pow(r, vec3(1.11)));
vec3 gaussian = exp(-pow(3.4 * r, vec3(1.6)));
vec3 fac = square(saturate(0.5 + r / 0.6));
vec3 profile = saturate(mix(gaussian, exponential, fac));
/* Mask off the end progressively to 0. */
profile *= saturate(1.0 - pow5f(lut_coord.x));
return vec4(profile, 0.0);
}
vec4 random_walk_sss_translucency(vec3 lut_coord)
{
/* Note that we only store the 1st (radius == 1) component.
* The others are here for debugging overall appearance. */
vec3 radii = vec3(1.0, 0.2, 0.1);
float thickness = lut_coord.x * SSS_TRANSMIT_LUT_RADIUS;
vec3 r = thickness / radii;
/* Manual fit based on cycles render of a backlit slab of varying thickness.
* Mean Error: 0.003
* Max Error: 0.016 */
vec3 scale = vec3(0.31, 0.47, 0.32);
vec3 exponent = vec3(-22.0, -5.8, -0.5);
vec3 profile = vec3(dot(scale, exp(exponent * r.r)),
dot(scale, exp(exponent * r.g)),
dot(scale, exp(exponent * r.b)));
profile = saturate(profile - 0.1);
/* Mask off the end progressively to 0. */
profile *= saturate(1.0 - pow5f(lut_coord.x));
return vec4(profile, 0.0);
}
void main()
{
/* Make sure coordinates are covering the whole [0..1] range at texel center. */
@ -186,6 +233,12 @@ void main()
case LUT_GGX_BSDF_SPLIT_SUM:
result = ggx_bsdf_split_sum(lut_normalized_coordinate);
break;
case LUT_BURLEY_SSS_PROFILE:
result = burley_sss_translucency(lut_normalized_coordinate);
break;
case LUT_RANDOM_WALK_SSS_PROFILE:
result = random_walk_sss_translucency(lut_normalized_coordinate);
break;
}
imageStore(table_img, ivec3(gl_GlobalInvocationID), result);
}

View File

@ -367,60 +367,6 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter
#endif
}
void output_renderpass_color(int id, vec4 color)
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
if (id >= 0) {
ivec2 texel = ivec2(gl_FragCoord.xy);
imageStore(rp_color_img, ivec3(texel, id), color);
}
#endif
}
void output_renderpass_value(int id, float value)
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
if (id >= 0) {
ivec2 texel = ivec2(gl_FragCoord.xy);
imageStore(rp_value_img, ivec3(texel, id), vec4(value));
}
#endif
}
void clear_aovs()
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.color_len; i++) {
output_renderpass_color(uniform_buf.render_pass.color_len + i, vec4(0));
}
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.value_len; i++) {
output_renderpass_value(uniform_buf.render_pass.value_len + i, 0.0);
}
#endif
}
void output_aov(vec4 color, float value, uint hash)
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.color_len; i++) {
if (uniform_buf.render_pass.aovs.hash_color[i].x == hash) {
imageStore(rp_color_img,
ivec3(ivec2(gl_FragCoord.xy), uniform_buf.render_pass.color_len + i),
color);
return;
}
}
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.value_len; i++) {
if (uniform_buf.render_pass.aovs.hash_value[i].x == hash) {
imageStore(rp_value_img,
ivec3(ivec2(gl_FragCoord.xy), uniform_buf.render_pass.value_len + i),
vec4(value));
return;
}
}
#endif
}
#ifdef EEVEE_MATERIAL_STUBS
# define attrib_load()
# define nodetree_displacement() vec3(0.0)

View File

@ -61,20 +61,20 @@ vec3 from_accumulation_space(vec3 color)
return color / (1.0 - dot(color, vec3(1.0)));
}
void gbuffer_load_closure_data(sampler2DArray gbuffer_closure_tx,
void gbuffer_load_closure_data(sampler2DArray gbuf_closure_tx,
ivec2 texel,
out ClosureDiffuse closure)
{
vec4 data_in = texelFetch(gbuffer_closure_tx, ivec3(texel, 1), 0);
vec4 data_in = texelFetch(gbuf_closure_tx, ivec3(texel, 1), 0);
closure.N = gbuffer_normal_unpack(data_in.xy);
}
void gbuffer_load_closure_data(sampler2DArray gbuffer_closure_tx,
void gbuffer_load_closure_data(sampler2DArray gbuf_closure_tx,
ivec2 texel,
out ClosureRefraction closure)
{
vec4 data_in = texelFetch(gbuffer_closure_tx, ivec3(texel, 1), 0);
vec4 data_in = texelFetch(gbuf_closure_tx, ivec3(texel, 1), 0);
closure.N = gbuffer_normal_unpack(data_in.xy);
if (gbuffer_is_refraction(data_in)) {
@ -87,11 +87,11 @@ void gbuffer_load_closure_data(sampler2DArray gbuffer_closure_tx,
}
}
void gbuffer_load_closure_data(sampler2DArray gbuffer_closure_tx,
void gbuffer_load_closure_data(sampler2DArray gbuf_closure_tx,
ivec2 texel,
out ClosureReflection closure)
{
vec4 data_in = texelFetch(gbuffer_closure_tx, ivec3(texel, 0), 0);
vec4 data_in = texelFetch(gbuf_closure_tx, ivec3(texel, 0), 0);
closure.N = gbuffer_normal_unpack(data_in.xy);
closure.roughness = data_in.z;
@ -116,9 +116,13 @@ void main()
#else
# error
#endif
gbuffer_load_closure_data(gbuffer_closure_tx, texel_fullres, center_closure);
gbuffer_load_closure_data(gbuf_closure_tx, texel_fullres, center_closure);
#if defined(RAYTRACE_DIFFUSE)
float roughness = 1.0;
#else
float roughness = center_closure.roughness;
#endif
float variance = imageLoad(in_variance_img, texel_fullres).r;
vec3 in_radiance = imageLoad(in_radiance_img, texel_fullres).rgb;
@ -168,7 +172,7 @@ void main()
continue;
}
gbuffer_load_closure_data(gbuffer_closure_tx, sample_texel, sample_closure);
gbuffer_load_closure_data(gbuf_closure_tx, sample_texel, sample_closure);
float depth_weight = bilateral_depth_weight(center_closure.N, center_P, sample_P);
float spatial_weight = bilateral_spatial_weight(filter_size, vec2(offset));

View File

@ -22,40 +22,22 @@
#pragma BLENDER_REQUIRE(eevee_bxdf_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void gbuffer_load_closure_data(sampler2DArray gbuffer_closure_tx,
void gbuffer_load_closure_data(sampler2DArray gbuf_closure_tx,
ivec2 texel,
out ClosureDiffuse closure)
{
vec4 data_in = texelFetch(gbuffer_closure_tx, ivec3(texel, 1), 0);
closure.N = gbuffer_normal_unpack(data_in.xy);
}
void gbuffer_load_closure_data(sampler2DArray gbuffer_closure_tx,
void gbuffer_load_closure_data(sampler2DArray gbuf_closure_tx,
ivec2 texel,
out ClosureRefraction closure)
{
vec4 data_in = texelFetch(gbuffer_closure_tx, ivec3(texel, 1), 0);
closure.N = gbuffer_normal_unpack(data_in.xy);
if (gbuffer_is_refraction(data_in)) {
closure.roughness = data_in.z;
closure.ior = gbuffer_ior_unpack(data_in.w);
}
else {
closure.roughness = 1.0;
closure.ior = 1.1;
}
}
void gbuffer_load_closure_data(sampler2DArray gbuffer_closure_tx,
void gbuffer_load_closure_data(sampler2DArray gbuf_closure_tx,
ivec2 texel,
out ClosureReflection closure)
{
vec4 data_in = texelFetch(gbuffer_closure_tx, ivec3(texel, 0), 0);
closure.N = gbuffer_normal_unpack(data_in.xy);
closure.roughness = data_in.z;
}
float bxdf_eval(ClosureDiffuse closure, vec3 L, vec3 V)
@ -88,19 +70,6 @@ bool neighbor_tile_mask_bit_get(uint tile_mask, ivec2 offset)
return flag_test(tile_mask, 1u << shift);
}
#if defined(RAYTRACE_DIFFUSE)
# define ClosureT ClosureDiffuse
# define CLOSURE_ACTIVE eClosureBits(CLOSURE_DIFFUSE)
#elif defined(RAYTRACE_REFRACT)
# define ClosureT ClosureRefraction
# define CLOSURE_ACTIVE eClosureBits(CLOSURE_REFRACTION)
#elif defined(RAYTRACE_REFLECT)
# define ClosureT ClosureReflection
# define CLOSURE_ACTIVE eClosureBits(CLOSURE_REFLECTION)
#else
# error
#endif
void main()
{
const uint tile_size = RAYTRACE_GROUP_SIZE;
@ -143,8 +112,8 @@ void main()
}
}
bool valid_texel = in_texture_range(texel_fullres, stencil_tx);
uint closure_bits = (!valid_texel) ? 0u : texelFetch(stencil_tx, texel_fullres, 0).r;
bool valid_texel = in_texture_range(texel_fullres, gbuf_header_tx);
uint closure_bits = (!valid_texel) ? 0u : texelFetch(gbuf_header_tx, texel_fullres, 0).r;
if (!flag_test(closure_bits, CLOSURE_ACTIVE)) {
imageStore(out_radiance_img, texel_fullres, vec4(FLT_11_11_10_MAX, 0.0));
imageStore(out_variance_img, texel_fullres, vec4(0.0));
@ -155,8 +124,17 @@ void main()
vec2 uv = (vec2(texel_fullres) + 0.5) * uniform_buf.raytrace.full_resolution_inv;
vec3 V = transform_direction(ViewMatrixInverse, get_view_vector_from_screen_uv(uv));
ClosureT closure;
gbuffer_load_closure_data(gbuffer_closure_tx, texel_fullres, closure);
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel_fullres);
#if defined(RAYTRACE_DIFFUSE)
ClosureDiffuse closure = gbuf.diffuse;
#elif defined(RAYTRACE_REFRACT)
ClosureRefraction closure = gbuf.refraction;
#elif defined(RAYTRACE_REFLECT)
ClosureReflection closure = gbuf.reflection;
#else
# error
#endif
uint sample_count = 16u;
float filter_size = 9.0;

View File

@ -22,58 +22,36 @@ void main()
ivec2 texel_fullres = texel * uniform_buf.raytrace.resolution_scale +
uniform_buf.raytrace.resolution_bias;
bool valid_texel = in_texture_range(texel_fullres, stencil_tx);
uint closure_bits = (!valid_texel) ? 0u : texelFetch(stencil_tx, texel_fullres, 0).r;
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel_fullres);
#if defined(RAYTRACE_REFLECT)
ClosureReflection closure;
eClosureBits closure_active = CLOSURE_REFLECTION;
const int gbuf_layer = 0;
#if defined(RAYTRACE_DIFFUSE)
bool valid_pixel = gbuf.has_diffuse;
#elif defined(RAYTRACE_REFLECT)
bool valid_pixel = gbuf.has_reflection;
#elif defined(RAYTRACE_REFRACT)
ClosureRefraction closure;
eClosureBits closure_active = CLOSURE_REFRACTION;
const int gbuf_layer = 1;
bool valid_pixel = gbuf.has_refraction;
#endif
if (!flag_test(closure_bits, closure_active)) {
if (!valid_pixel) {
imageStore(out_ray_data_img, texel, vec4(0.0));
return;
}
vec2 uv = (vec2(texel_fullres) + 0.5) / vec2(textureSize(stencil_tx, 0).xy);
vec2 uv = (vec2(texel_fullres) + 0.5) / vec2(textureSize(gbuf_header_tx, 0).xy);
vec3 V = transform_direction(ViewMatrixInverse, get_view_vector_from_screen_uv(uv));
vec2 noise = utility_tx_fetch(utility_tx, vec2(texel), UTIL_BLUE_NOISE_LAYER).rg;
/* Load GBuffer data. */
vec4 gbuffer_packed = texelFetch(gbuffer_closure_tx, ivec3(texel_fullres, gbuf_layer), 0);
closure.N = gbuffer_normal_unpack(gbuffer_packed.xy);
#if defined(RAYTRACE_REFLECT)
closure.roughness = gbuffer_packed.z;
#if defined(RAYTRACE_DIFFUSE)
ClosureDiffuse closure = gbuf.diffuse;
#elif defined(RAYTRACE_REFLECT)
ClosureReflection closure = gbuf.reflection;
#elif defined(RAYTRACE_REFRACT)
if (gbuffer_is_refraction(gbuffer_packed)) {
closure.roughness = gbuffer_packed.z;
closure.ior = gbuffer_ior_unpack(gbuffer_packed.w);
}
else {
/* Avoid producing incorrect ray directions. */
closure.ior = 1.1;
closure.roughness = 0.0;
}
ClosureRefraction closure = gbuf.refraction;
#endif
float pdf;
vec3 ray_direction = ray_generate_direction(noise.xy, closure, V, pdf);
#if defined(RAYTRACE_REFRACT)
if (gbuffer_is_refraction(gbuffer_packed) && closure_active != CLOSURE_REFRACTION) {
/* Discard incorrect rays. */
pdf = 0.0;
}
#endif
/* Store inverse pdf to speedup denoising.
* Limit to the smallest non-0 value that the format can encode.
* Strangely it does not correspond to the IEEE spec. */

View File

@ -40,15 +40,17 @@ void main()
barrier();
ivec2 texel = min(ivec2(gl_GlobalInvocationID.xy), textureSize(stencil_tx, 0) - 1);
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
eClosureBits closure_bits = eClosureBits(texelFetch(stencil_tx, texel, 0).r);
bool valid_texel = in_texture_range(texel, gbuf_header_tx);
uint closure_bits = (!valid_texel) ? 0u : texelFetch(gbuf_header_tx, texel, 0).r;
if (flag_test(closure_bits, uniform_buf.raytrace.closure_active)) {
int gbuffer_layer = uniform_buf.raytrace.closure_active == CLOSURE_REFRACTION ? 1 : 0;
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel);
vec4 gbuffer_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, gbuffer_layer), 0);
float roughness = gbuffer_packed.z;
float roughness = (uniform_buf.raytrace.closure_active == CLOSURE_REFRACTION) ?
gbuf.refraction.roughness :
gbuf.reflection.roughness;
if (ray_glossy_factor(roughness) > 0.0) {
/* We don't care about race condition here. */

View File

@ -45,7 +45,7 @@ void main()
float noise_offset = sampling_rng_1D_get(SAMPLING_RAYTRACE_W);
float rand_trace = interlieved_gradient_noise(vec2(texel), 5.0, noise_offset);
#if defined(RAYTRACE_REFLECT)
#if defined(RAYTRACE_REFLECT) || defined(RAYTRACE_DIFFUSE)
const bool discard_backface = true;
const bool allow_self_intersection = false;
#elif defined(RAYTRACE_REFRACT)

View File

@ -0,0 +1,57 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
void output_renderpass_color(int id, vec4 color)
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
if (id >= 0) {
ivec2 texel = ivec2(gl_FragCoord.xy);
imageStore(rp_color_img, ivec3(texel, id), color);
}
#endif
}
void output_renderpass_value(int id, float value)
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
if (id >= 0) {
ivec2 texel = ivec2(gl_FragCoord.xy);
imageStore(rp_value_img, ivec3(texel, id), vec4(value));
}
#endif
}
void clear_aovs()
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.color_len; i++) {
output_renderpass_color(uniform_buf.render_pass.color_len + i, vec4(0));
}
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.value_len; i++) {
output_renderpass_value(uniform_buf.render_pass.value_len + i, 0.0);
}
#endif
}
void output_aov(vec4 color, float value, uint hash)
{
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.color_len; i++) {
if (uniform_buf.render_pass.aovs.hash_color[i].x == hash) {
imageStore(rp_color_img,
ivec3(ivec2(gl_FragCoord.xy), uniform_buf.render_pass.color_len + i),
color);
return;
}
}
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.value_len; i++) {
if (uniform_buf.render_pass.aovs.hash_value[i].x == hash) {
imageStore(rp_value_img,
ivec3(ivec2(gl_FragCoord.xy), uniform_buf.render_pass.value_len + i),
vec4(value));
return;
}
}
#endif
}

View File

@ -124,10 +124,21 @@ vec3 sample_cylinder(vec2 rand)
vec3 sample_sphere(vec2 rand)
{
float omega = rand.y * 2.0 * M_PI;
float cos_theta = rand.x * 2.0 - 1.0;
float sin_theta = safe_sqrt(1.0 - cos_theta * cos_theta);
return vec3(sin_theta * vec2(cos(omega), sin(omega)), cos_theta);
return vec3(sin_theta * sample_circle(rand.y), cos_theta);
}
/**
* Uniform hemisphere distribution.
* \a rand is 2 random float in the [0..1] range.
* Returns point on a Z positive hemisphere of radius 1 and centered on the origin.
*/
vec3 sample_hemisphere(vec2 rand)
{
float cos_theta = rand.x;
float sin_theta = safe_sqrt(1.0 - sqr(cos_theta));
return vec3(sin_theta * sample_circle(rand.y), cos_theta);
}
/** \} */

View File

@ -20,31 +20,6 @@
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
vec3 burley_setup(vec3 radius, vec3 albedo)
{
/* Scale albedo because we can have HDR value caused by BSDF sampling. */
vec3 A = albedo / max(1e-6, max_v3(albedo));
/* Diffuse surface transmission, equation (6). */
vec3 s = 1.9 - A + 3.5 * sqr(A - 0.8);
/* Mean free path length adapted to fit ancient Cubic and Gaussian models. */
vec3 l = 0.25 * M_1_PI * radius;
return l / s;
}
vec3 burley_eval(vec3 d, float r)
{
/* Slide 33. */
vec3 exp_r_3_d = exp(-r / (3.0 * d));
vec3 exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
/* NOTE:
* - Surface albedo is applied at the end.
* - This is normalized diffuse model, so the equation is multiplied
* by 2*pi, which also matches `cdf()`.
*/
return (exp_r_d + exp_r_3_d) / (4.0 * d);
}
void main(void)
{
vec2 center_uv = uvcoordsvar.xy;
@ -53,22 +28,16 @@ void main(void)
float gbuffer_depth = texelFetch(hiz_tx, texel, 0).r;
vec3 vP = get_view_space_from_depth(center_uv, gbuffer_depth);
vec4 color_1_packed = texelFetch(gbuffer_color_tx, ivec3(texel, 1), 0);
vec4 gbuffer_2_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, 2), 0);
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel);
ClosureDiffuse diffuse;
diffuse.sss_radius = gbuffer_sss_radii_unpack(gbuffer_2_packed.xyz);
diffuse.sss_id = gbuffer_object_id_unorm16_unpack(gbuffer_2_packed.w);
diffuse.color = gbuffer_color_unpack(color_1_packed);
if (diffuse.sss_id == 0u) {
if (gbuf.diffuse.sss_id == 0u) {
/* Normal diffuse is already in combined pass. */
/* Refraction also go into this case. */
out_combined = vec4(0.0);
return;
}
float max_radius = max_v3(diffuse.sss_radius);
float max_radius = max_v3(gbuf.diffuse.sss_radius);
float homcoord = ProjectionMatrix[2][3] * vP.z + ProjectionMatrix[3][3];
vec2 sample_scale = vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) *
@ -81,8 +50,11 @@ void main(void)
return;
}
diffuse.sss_radius = max(vec3(1e-4), diffuse.sss_radius / max_radius) * max_radius;
vec3 d = burley_setup(diffuse.sss_radius, diffuse.color);
/* Avoid too small radii that have float imprecision. */
vec3 clamped_sss_radius = max(vec3(1e-4), gbuf.diffuse.sss_radius / max_radius) * max_radius;
/* Scale albedo because we can have HDR value caused by BSDF sampling. */
vec3 albedo = gbuf.diffuse.color / max(1e-6, max_v3(gbuf.diffuse.color));
vec3 d = burley_setup(clamped_sss_radius, albedo);
/* Do not rotate too much to avoid too much cache misses. */
float golden_angle = M_PI * (3.0 - sqrt(5.0));
@ -110,7 +82,7 @@ void main(void)
vec3 sample_radiance = sample_data.rgb;
uint sample_sss_id = uint(sample_data.a);
if (sample_sss_id != diffuse.sss_id) {
if (sample_sss_id != gbuf.diffuse.sss_id) {
continue;
}
@ -139,7 +111,7 @@ void main(void)
accum -= texelFetch(radiance_tx, texel, 0).rgb;
/* Apply surface color on final radiance. */
accum *= diffuse.color;
accum *= gbuf.diffuse.color;
/* Debug, detect NaNs. */
if (any(isnan(accum))) {

View File

@ -16,6 +16,7 @@
#pragma BLENDER_REQUIRE(eevee_ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_renderpass_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
vec4 closure_to_rgba(Closure cl)
@ -86,56 +87,62 @@ void main()
/* ----- GBuffer output ----- */
if (true) {
uint header = 0u;
if (g_reflection_data.weight > 0.0) {
/* Reflection. */
vec4 out_reflect = vec4(gbuffer_normal_pack(g_reflection_data.N),
g_reflection_data.roughness,
g_reflection_data.roughness);
imageStore(out_gbuff_closure_img, ivec3(out_texel, 0), out_reflect);
vec4 closure;
closure.xy = gbuffer_normal_pack(g_reflection_data.N);
closure.z = g_reflection_data.roughness;
closure.w = 0.0;
imageStore(out_gbuf_closure_img, ivec3(out_texel, 0), closure);
vec4 color = gbuffer_color_pack(g_reflection_data.color);
imageStore(out_gbuff_color_img, ivec3(out_texel, 0), color);
imageStore(out_gbuf_color_img, ivec3(out_texel, 0), color);
header |= CLOSURE_REFLECTION;
}
/* TODO(fclem) other RNG. */
float refract_rand = fract(g_closure_rand * 6.1803398875);
float combined_weight = g_refraction_data.weight + g_diffuse_data.weight;
bool output_refraction = combined_weight > 0.0 &&
(refract_rand * combined_weight) < g_refraction_data.weight;
if (output_refraction) {
/* Refraction. */
vec4 closure;
closure.xy = gbuffer_normal_pack(g_refraction_data.N);
closure.z = g_refraction_data.roughness;
closure.w = gbuffer_ior_pack(g_refraction_data.ior);
/* Clamp to just bellow 1 to be able to distinguish between refraction and diffuse.
* Ceiling value is chosen by the storage format (16bit UNORM). */
closure.w = min(closure.w, float(0xFFFFu - 1u) / float(0xFFFFu));
imageStore(out_gbuff_closure_img, ivec3(out_texel, 1), closure);
if (combined_weight > 0.0) {
/* TODO(fclem) other RNG. */
float refract_rand = fract(g_closure_rand * 6.1803398875);
bool output_refraction = (refract_rand * combined_weight) < g_refraction_data.weight;
if (output_refraction) {
/* Refraction. */
vec4 closure;
closure.xy = gbuffer_normal_pack(g_refraction_data.N);
closure.z = g_refraction_data.roughness;
closure.w = gbuffer_ior_pack(g_refraction_data.ior);
imageStore(out_gbuf_closure_img, ivec3(out_texel, 1), closure);
vec4 color = gbuffer_color_pack(g_refraction_data.color);
imageStore(out_gbuff_color_img, ivec3(out_texel, 1), color);
}
else {
/* Diffuse. */
vec4 closure;
closure.xy = gbuffer_normal_pack(g_diffuse_data.N);
closure.z = gbuffer_thickness_pack(thickness);
/* Used to detect the refraction case. Could be used for roughness. */
closure.w = 1.0;
imageStore(out_gbuff_closure_img, ivec3(out_texel, 1), closure);
vec4 color = gbuffer_color_pack(g_refraction_data.color);
imageStore(out_gbuf_color_img, ivec3(out_texel, 1), color);
header |= CLOSURE_REFRACTION;
}
else {
/* Diffuse. */
vec4 closure;
closure.xy = gbuffer_normal_pack(g_diffuse_data.N);
closure.z = gbuffer_thickness_pack(thickness);
closure.w = 0.0; /* Unused. */
imageStore(out_gbuf_closure_img, ivec3(out_texel, 1), closure);
vec4 color = gbuffer_color_pack(g_diffuse_data.color);
imageStore(out_gbuff_color_img, ivec3(out_texel, 1), color);
vec4 color = gbuffer_color_pack(g_diffuse_data.color);
imageStore(out_gbuf_color_img, ivec3(out_texel, 1), color);
header |= CLOSURE_DIFFUSE;
}
if (g_diffuse_data.sss_id > 0) {
/* SubSurface Scattering. */
vec4 closure;
closure.xyz = gbuffer_sss_radii_pack(g_diffuse_data.sss_radius);
closure.w = gbuffer_object_id_unorm16_pack(uint(resource_id));
imageStore(out_gbuf_closure_img, ivec3(out_texel, 2), closure);
header |= CLOSURE_SSS;
}
}
if (true) {
/* SubSurface Scattering. */
vec4 closure;
closure.xyz = gbuffer_sss_radii_pack(g_diffuse_data.sss_radius);
closure.w = gbuffer_object_id_unorm16_pack(g_diffuse_data.sss_id > 0 ? uint(resource_id) : 0);
imageStore(out_gbuff_closure_img, ivec3(out_texel, 2), closure);
}
imageStore(out_gbuf_header_img, out_texel, uvec4(header));
/* ----- Radiance output ----- */

View File

@ -16,6 +16,7 @@
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_renderpass_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_volume_lib.glsl)
vec4 closure_to_rgba(Closure cl)

View File

@ -13,6 +13,7 @@
#pragma BLENDER_REQUIRE(eevee_attributes_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_renderpass_lib.glsl)
void main()
{

View File

@ -20,7 +20,7 @@
void main()
{
int surfel_index = int(gl_GlobalInvocationID.x);
if (surfel_index >= capture_info_buf.surfel_len) {
if (surfel_index >= int(capture_info_buf.surfel_len)) {
return;
}
@ -32,5 +32,5 @@ void main()
surfel_buf[surfel_index].ray_distance = ray_distance;
/* NOTE: We only need to init the `list_start_buf` to -1 for the whole list to be valid since
* every surfel will load its `next` value from the list head. */
surfel_buf[surfel_index].next = atomicExchange(list_start_buf[list_index], surfel_index);
// surfel_buf[surfel_index].next = atomicExchange(list_start_buf[list_index], surfel_index);
}

View File

@ -5,66 +5,74 @@
#include "eevee_defines.hh"
#include "gpu_shader_create_info.hh"
#define image_out(slot, qualifier, format, name) \
image(slot, format, qualifier, ImageType::FLOAT_2D, name, Frequency::PASS)
#define image_array_out(slot, qualifier, format, name) \
image(slot, format, qualifier, ImageType::FLOAT_2D_ARRAY, name, Frequency::PASS)
#define image_out(slot, format, name) \
image(slot, format, Qualifier::WRITE, ImageType::FLOAT_2D, name, Frequency::PASS)
#define image_in(slot, format, name) \
image(slot, format, Qualifier::READ, ImageType::FLOAT_2D, name, Frequency::PASS)
/**
* Specific deferred pass accumulate the computed lighting to either:
* - a split diffuse / specular temporary light buffer.
* or to
* - the combined pass & the light render-pass (if needed).
*
* This is in order to minimize the number of blending step.
*/
GPU_SHADER_CREATE_INFO(eevee_deferred_base)
GPU_SHADER_CREATE_INFO(eevee_gbuffer_data)
.sampler(7, ImageType::UINT_2D, "gbuf_header_tx")
.sampler(8, ImageType::FLOAT_2D_ARRAY, "gbuf_closure_tx")
.sampler(9, ImageType::FLOAT_2D_ARRAY, "gbuf_color_tx");
GPU_SHADER_CREATE_INFO(eevee_deferred_light)
.fragment_source("eevee_deferred_light_frag.glsl")
/* Early fragment test is needed to avoid processing fragments without correct GBuffer data. */
.early_fragment_test(true)
/* Select which output to write to. */
.push_constant(Type::BOOL, "is_last_eval_pass")
/* Combined pass output. */
.fragment_out(0, Type::VEC4, "out_radiance", DualBlend::SRC_0)
.fragment_out(0, Type::VEC4, "out_transmittance", DualBlend::SRC_1)
/* Chaining to next pass. */
.image_out(2, Qualifier::WRITE, GPU_RGBA16F, "out_diffuse_light_img")
.image_out(3, Qualifier::WRITE, GPU_RGBA16F, "out_specular_light_img");
GPU_SHADER_CREATE_INFO(eevee_deferred_light_base)
.fragment_source("eevee_deferred_light_frag.glsl")
.sampler(0, ImageType::FLOAT_2D_ARRAY, "gbuffer_closure_tx")
.sampler(1, ImageType::FLOAT_2D_ARRAY, "gbuffer_color_tx")
.image(4,
RAYTRACE_RADIANCE_FORMAT,
Qualifier::READ,
ImageType::FLOAT_2D,
"indirect_reflection_img")
.image(5,
RAYTRACE_RADIANCE_FORMAT,
Qualifier::READ,
ImageType::FLOAT_2D,
"indirect_refraction_img")
/* TODO(@fclem): These could use the sub-pass feature. */
.image_out(2, GPU_RGBA16F, "direct_diffuse_img")
.image_out(3, GPU_RGBA16F, "direct_reflect_img")
.image_out(4, GPU_RGBA16F, "direct_refract_img")
.define("SSS_TRANSMITTANCE")
.additional_info("eevee_shared",
"eevee_gbuffer_data",
"eevee_utility_texture",
"eevee_sampling_data",
"eevee_light_data",
"eevee_reflection_probe_data",
"eevee_lightprobe_data",
"eevee_shadow_data",
"eevee_deferred_base",
"eevee_hiz_data",
"eevee_render_pass_out",
"draw_view",
"draw_fullscreen");
GPU_SHADER_CREATE_INFO(eevee_deferred_light)
.additional_info("eevee_deferred_light_base")
.define("DO_REFLECTION_PROBES")
"draw_fullscreen")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(eevee_deferred_light_diffuse)
.additional_info("eevee_deferred_light_base")
GPU_SHADER_CREATE_INFO(eevee_deferred_combine)
/* Early fragment test is needed to avoid processing fragments without correct GBuffer data. */
.early_fragment_test(true)
/* Inputs. */
.image_in(2, GPU_RGBA16F, "direct_diffuse_img")
.image_in(3, GPU_RGBA16F, "direct_reflect_img")
.image_in(4, GPU_RGBA16F, "direct_refract_img")
.image_in(5, RAYTRACE_RADIANCE_FORMAT, "indirect_diffuse_img")
.image_in(6, RAYTRACE_RADIANCE_FORMAT, "indirect_reflect_img")
.image_in(7, RAYTRACE_RADIANCE_FORMAT, "indirect_refract_img")
.fragment_out(0, Type::VEC4, "out_combined")
.additional_info("eevee_shared",
"eevee_gbuffer_data",
"eevee_render_pass_out",
"draw_fullscreen")
.fragment_source("eevee_deferred_combine_frag.glsl")
.do_static_compilation(true);
#undef image_array_out
GPU_SHADER_CREATE_INFO(eevee_deferred_capture_eval)
/* Early fragment test is needed to avoid processing fragments without correct GBuffer data. */
.early_fragment_test(true)
/* Inputs. */
.fragment_out(0, Type::VEC4, "out_radiance")
.define("SSS_TRANSMITTANCE")
.additional_info("eevee_shared",
"eevee_gbuffer_data",
"eevee_utility_texture",
"eevee_sampling_data",
"eevee_light_data",
"eevee_lightprobe_data",
"eevee_shadow_data",
"eevee_hiz_data",
"draw_view",
"draw_fullscreen")
.fragment_source("eevee_deferred_capture_frag.glsl")
.do_static_compilation(true);
#undef image_out
#undef image_in

View File

@ -127,8 +127,9 @@ GPU_SHADER_CREATE_INFO(eevee_surf_deferred)
.fragment_out(0, Type::VEC4, "out_transmittance", DualBlend::SRC_1)
/* Everything is stored inside a two layered target, one for each format. This is to fit the
* limitation of the number of images we can bind on a single shader. */
.image_array_out(GBUF_CLOSURE_SLOT, Qualifier::WRITE, GPU_RGBA16, "out_gbuff_closure_img")
.image_array_out(GBUF_COLOR_SLOT, Qualifier::WRITE, GPU_RGB10_A2, "out_gbuff_color_img")
.image_array_out(GBUF_CLOSURE_SLOT, Qualifier::WRITE, GPU_RGBA16, "out_gbuf_closure_img")
.image_array_out(GBUF_COLOR_SLOT, Qualifier::WRITE, GPU_RGB10_A2, "out_gbuf_color_img")
.image(GBUF_HEADER_SLOT, GPU_R8UI, Qualifier::WRITE, ImageType::UINT_2D, "out_gbuf_header_img")
.fragment_source("eevee_surf_deferred_frag.glsl")
.additional_info("eevee_global_ubo",
"eevee_utility_texture",

View File

@ -7,9 +7,10 @@
GPU_SHADER_CREATE_INFO(eevee_subsurface_eval)
.do_static_compilation(true)
.additional_info("eevee_shared", "eevee_global_ubo", "eevee_render_pass_out")
.sampler(0, ImageType::FLOAT_2D_ARRAY, "gbuffer_closure_tx")
.sampler(1, ImageType::FLOAT_2D_ARRAY, "gbuffer_color_tx")
.additional_info("eevee_shared",
"eevee_gbuffer_data",
"eevee_global_ubo",
"eevee_render_pass_out")
.sampler(2, ImageType::FLOAT_2D, "radiance_tx")
.early_fragment_test(true)
.fragment_out(0, Type::VEC4, "out_combined")

View File

@ -6,13 +6,20 @@
#include "gpu_shader_create_info.hh"
#define EEVEE_RAYTRACE_CLOSURE_VARIATION(name, ...) \
GPU_SHADER_CREATE_INFO(name##_diffuse) \
.do_static_compilation(true) \
.define("RAYTRACE_DIFFUSE") \
.define("CLOSURE_ACTIVE", "eClosureBits(CLOSURE_DIFFUSE)") \
.additional_info(#name); \
GPU_SHADER_CREATE_INFO(name##_reflect) \
.do_static_compilation(true) \
.define("RAYTRACE_REFLECT") \
.define("CLOSURE_ACTIVE", "eClosureBits(CLOSURE_REFLECTION)") \
.additional_info(#name); \
GPU_SHADER_CREATE_INFO(name##_refract) \
.do_static_compilation(true) \
.define("RAYTRACE_REFRACT") \
.define("CLOSURE_ACTIVE", "eClosureBits(CLOSURE_REFRACTION)") \
.additional_info(#name);
/* -------------------------------------------------------------------- */
@ -22,10 +29,8 @@
GPU_SHADER_CREATE_INFO(eevee_ray_tile_classify)
.do_static_compilation(true)
.local_group_size(RAYTRACE_GROUP_SIZE, RAYTRACE_GROUP_SIZE)
.additional_info("eevee_shared", "eevee_global_ubo")
.additional_info("eevee_shared", "eevee_gbuffer_data", "eevee_global_ubo")
.typedef_source("draw_shader_shared.h")
.sampler(0, ImageType::FLOAT_2D_ARRAY, "gbuffer_closure_tx")
.sampler(1, ImageType::UINT_2D, "stencil_tx")
.image(0, RAYTRACE_TILEMASK_FORMAT, Qualifier::WRITE, ImageType::UINT_2D, "tile_mask_img")
.storage_buf(0, Qualifier::WRITE, "DispatchCommand", "ray_dispatch_buf")
.storage_buf(1, Qualifier::WRITE, "DispatchCommand", "denoise_dispatch_buf")
@ -46,12 +51,11 @@ GPU_SHADER_CREATE_INFO(eevee_ray_tile_compact)
GPU_SHADER_CREATE_INFO(eevee_ray_generate)
.local_group_size(RAYTRACE_GROUP_SIZE, RAYTRACE_GROUP_SIZE)
.additional_info("eevee_shared",
"eevee_gbuffer_data",
"eevee_global_ubo",
"eevee_sampling_data",
"draw_view",
"eevee_utility_texture")
.sampler(0, ImageType::UINT_2D, "stencil_tx")
.sampler(1, ImageType::FLOAT_2D_ARRAY, "gbuffer_closure_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_ray_data_img")
.storage_buf(4, Qualifier::READ, "uint", "tiles_coord_buf[]")
.compute_source("eevee_ray_generate_comp.glsl");
@ -66,7 +70,7 @@ GPU_SHADER_CREATE_INFO(eevee_ray_trace_fallback)
"draw_view",
"eevee_reflection_probe_data")
.image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "ray_data_img")
.image(1, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "ray_time_img")
.image(1, RAYTRACE_RAYTIME_FORMAT, Qualifier::WRITE, ImageType::FLOAT_2D, "ray_time_img")
.image(2, RAYTRACE_RADIANCE_FORMAT, Qualifier::WRITE, ImageType::FLOAT_2D, "ray_radiance_img")
.sampler(1, ImageType::DEPTH_2D, "depth_tx")
.storage_buf(4, Qualifier::READ, "uint", "tiles_coord_buf[]")
@ -81,7 +85,7 @@ GPU_SHADER_CREATE_INFO(eevee_ray_trace_screen)
"eevee_hiz_data",
"eevee_reflection_probe_data")
.image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "ray_data_img")
.image(1, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "ray_time_img")
.image(1, RAYTRACE_RAYTIME_FORMAT, Qualifier::WRITE, ImageType::FLOAT_2D, "ray_time_img")
.image(2, RAYTRACE_RADIANCE_FORMAT, Qualifier::WRITE, ImageType::FLOAT_2D, "ray_radiance_img")
.sampler(0, ImageType::FLOAT_2D, "screen_radiance_tx")
.sampler(1, ImageType::DEPTH_2D, "depth_tx")
@ -93,15 +97,14 @@ EEVEE_RAYTRACE_CLOSURE_VARIATION(eevee_ray_trace_screen)
GPU_SHADER_CREATE_INFO(eevee_ray_denoise_spatial)
.local_group_size(RAYTRACE_GROUP_SIZE, RAYTRACE_GROUP_SIZE)
.additional_info("eevee_shared",
"eevee_gbuffer_data",
"eevee_global_ubo",
"eevee_sampling_data",
"draw_view",
"eevee_utility_texture")
.sampler(0, ImageType::FLOAT_2D_ARRAY, "gbuffer_closure_tx")
.sampler(1, ImageType::UINT_2D, "stencil_tx")
.sampler(3, ImageType::DEPTH_2D, "depth_tx")
.image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "ray_data_img")
.image(1, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "ray_time_img")
.image(1, RAYTRACE_RAYTIME_FORMAT, Qualifier::READ, ImageType::FLOAT_2D, "ray_time_img")
.image(2, RAYTRACE_RADIANCE_FORMAT, Qualifier::READ, ImageType::FLOAT_2D, "ray_radiance_img")
.image(3, RAYTRACE_RADIANCE_FORMAT, Qualifier::WRITE, ImageType::FLOAT_2D, "out_radiance_img")
.image(4, RAYTRACE_VARIANCE_FORMAT, Qualifier::WRITE, ImageType::FLOAT_2D, "out_variance_img")
@ -130,8 +133,11 @@ GPU_SHADER_CREATE_INFO(eevee_ray_denoise_temporal)
GPU_SHADER_CREATE_INFO(eevee_ray_denoise_bilateral)
.local_group_size(RAYTRACE_GROUP_SIZE, RAYTRACE_GROUP_SIZE)
.additional_info("eevee_shared", "eevee_global_ubo", "eevee_sampling_data", "draw_view")
.sampler(0, ImageType::FLOAT_2D_ARRAY, "gbuffer_closure_tx")
.additional_info("eevee_shared",
"eevee_gbuffer_data",
"eevee_global_ubo",
"eevee_sampling_data",
"draw_view")
.sampler(1, ImageType::DEPTH_2D, "depth_tx")
.image(1, RAYTRACE_RADIANCE_FORMAT, Qualifier::READ, ImageType::FLOAT_2D, "in_radiance_img")
.image(2, RAYTRACE_RADIANCE_FORMAT, Qualifier::WRITE, ImageType::FLOAT_2D, "out_radiance_img")

View File

@ -1451,14 +1451,21 @@ static void test_eevee_lut_gen()
auto brdf_ggx_gen = Precompute(manager, LUT_GGX_BRDF_SPLIT_SUM, {64, 64, 1}).data<float2>();
auto btdf_ggx_gen = Precompute(manager, LUT_GGX_BTDF_IOR_GT_ONE, {64, 64, 16}).data<float1>();
auto bsdf_ggx_gen = Precompute(manager, LUT_GGX_BSDF_SPLIT_SUM, {64, 64, 16}).data<float3>();
auto burley_gen = Precompute(manager, LUT_BURLEY_SSS_PROFILE, {64, 1, 1}).data<float1>();
auto rand_walk_gen = Precompute(manager, LUT_RANDOM_WALK_SSS_PROFILE, {64, 1, 1}).data<float1>();
Span<float2> brdf_ggx_lut((const float2 *)&eevee::lut::brdf_ggx, 64 * 64);
Span<float1> btdf_ggx_lut((const float1 *)&eevee::lut::btdf_ggx, 64 * 64 * 16);
Span<float3> bsdf_ggx_lut((const float3 *)&eevee::lut::bsdf_ggx, 64 * 64 * 16);
Span<float1> burley_sss_lut((const float1 *)&eevee::lut::burley_sss_profile, 64);
Span<float1> rand_walk_lut((const float1 *)&eevee::lut::random_walk_sss_profile, 64);
EXPECT_NEAR_ARRAY_ND(brdf_ggx_lut.data(), brdf_ggx_gen.data(), brdf_ggx_gen.size(), 2, 1e-4f);
EXPECT_NEAR_ARRAY_ND(btdf_ggx_lut.data(), btdf_ggx_gen.data(), btdf_ggx_gen.size(), 1, 1e-4f);
EXPECT_NEAR_ARRAY_ND(bsdf_ggx_lut.data(), bsdf_ggx_gen.data(), bsdf_ggx_gen.size(), 3, 1e-4f);
const float eps = 3e-3f;
EXPECT_NEAR_ARRAY_ND(brdf_ggx_lut.data(), brdf_ggx_gen.data(), brdf_ggx_gen.size(), 2, eps);
EXPECT_NEAR_ARRAY_ND(btdf_ggx_lut.data(), btdf_ggx_gen.data(), btdf_ggx_gen.size(), 1, eps);
EXPECT_NEAR_ARRAY_ND(bsdf_ggx_lut.data(), bsdf_ggx_gen.data(), bsdf_ggx_gen.size(), 3, eps);
EXPECT_NEAR_ARRAY_ND(burley_gen.data(), burley_sss_lut.data(), burley_sss_lut.size(), 1, eps);
EXPECT_NEAR_ARRAY_ND(rand_walk_gen.data(), rand_walk_lut.data(), rand_walk_lut.size(), 1, eps);
GPU_render_end();
}

View File

@ -1225,7 +1225,7 @@ void create_stroke(Main &bmain, Object &object, float4x4 matrix, const int frame
grease_pencil.insert_blank_frame(layer_color, frame_number, 0, BEZT_KEYTYPE_KEYFRAME);
GreasePencilDrawing &drawing = *reinterpret_cast<GreasePencilDrawing *>(
grease_pencil.drawings(1));
grease_pencil.drawing(1));
drawing.geometry.wrap() = create_drawing_data(
stroke_positions, stroke_radii, stroke_opacities, {0, 175}, {material_index}, {75}, matrix);
}
@ -1286,7 +1286,7 @@ void create_suzanne(Main &bmain, Object &object, float4x4 matrix, const int fram
grease_pencil.insert_blank_frame(layer_fills, frame_number, 0, BEZT_KEYTYPE_KEYFRAME);
GreasePencilDrawing *drawing_lines = reinterpret_cast<GreasePencilDrawing *>(
grease_pencil.drawings(0));
grease_pencil.drawing(0));
drawing_lines->geometry.wrap() = create_drawing_data(monkey_line_positions,
monkey_line_radii,
monkey_line_opacities,
@ -1296,7 +1296,7 @@ void create_suzanne(Main &bmain, Object &object, float4x4 matrix, const int fram
matrix);
GreasePencilDrawing *drawing_fills = reinterpret_cast<GreasePencilDrawing *>(
grease_pencil.drawings(1));
grease_pencil.drawing(1));
drawing_fills->geometry.wrap() = create_drawing_data(monkey_fill_positions,
monkey_fill_radii,
monkey_fill_opacities,

View File

@ -5003,8 +5003,7 @@ int UI_preview_tile_size_x(const int size_px)
int UI_preview_tile_size_y(const int size_px)
{
const uiStyle *style = UI_style_get();
const float font_height = style->widget.points * UI_SCALE_FAC;
const float font_height = UI_UNIT_Y;
/* Add some extra padding to make things less tight vertically. */
const float pad = PREVIEW_TILE_PAD;

View File

@ -544,7 +544,7 @@ static void ui_block_colorpicker(uiBlock *block,
float(PICKER_TYPE_RGB),
0,
0,
"");
TIP_("Red, Green, Blue"));
UI_but_flag_disable(bt, UI_BUT_UNDO);
UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT);
UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr);
@ -562,7 +562,8 @@ static void ui_block_colorpicker(uiBlock *block,
PICKER_TYPE_HSV,
0,
0,
"");
(U.color_picker_type == USER_CP_CIRCLE_HSL) ? TIP_("Hue, Saturation, Lightness") :
TIP_("Hue, Saturation, Value"));
UI_but_flag_disable(bt, UI_BUT_UNDO);
UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT);
UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr);
@ -580,7 +581,7 @@ static void ui_block_colorpicker(uiBlock *block,
PICKER_TYPE_HEX,
0,
0,
"");
TIP_("Color as hexadecimal values"));
UI_but_flag_disable(bt, UI_BUT_UNDO);
UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT);
UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr);
@ -804,7 +805,7 @@ static void ui_block_colorpicker(uiBlock *block,
uiDefBut(block,
UI_BTYPE_LABEL,
0,
IFACE_("(Gamma Corrected)"),
IFACE_("(Gamma corrected)"),
0,
yco - UI_UNIT_Y,
butwidth,

View File

@ -262,8 +262,7 @@ static void ui_tooltip_region_draw_cb(const bContext * /*C*/, ARegion *region)
}
else if (field->format.style == UI_TIP_STYLE_IMAGE) {
bbox.ymax -= field->image_size[0];
bbox.ymin -= field->image_size[0];
bbox.ymax -= field->image_size[1];
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR);
@ -1251,7 +1250,7 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
if (field->format.style == UI_TIP_STYLE_IMAGE) {
fonth += field->image_size[1];
w = field->image_size[0];
w = max_ii(w, field->image_size[0]);
}
fontw = max_ii(fontw, w);

View File

@ -90,7 +90,7 @@ void PaintOperation::on_stroke_done(const bContext &C)
int index_orig = active_layer_orig.drawing_index_at(scene->r.cfra);
bke::greasepencil::Drawing &drawing_orig =
reinterpret_cast<GreasePencilDrawing *>(grease_pencil_orig.drawings(index_orig))->wrap();
reinterpret_cast<GreasePencilDrawing *>(grease_pencil_orig.drawing(index_orig))->wrap();
const Span<bke::greasepencil::StrokePoint> stroke_points =
grease_pencil_eval.runtime->stroke_buffer();

View File

@ -1093,9 +1093,13 @@ static bool delete_action_keys(bAnimContext *ac)
changed = ED_gpencil_layer_frames_delete((bGPDlayer *)ale->data);
}
else if (ale->type == ANIMTYPE_GREASE_PENCIL_LAYER) {
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(ale->id);
changed = blender::ed::greasepencil::remove_all_selected_frames(
*reinterpret_cast<GreasePencil *>(ale->id),
static_cast<GreasePencilLayer *>(ale->data)->wrap());
*grease_pencil, static_cast<GreasePencilLayer *>(ale->data)->wrap());
if (changed) {
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
}
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
changed = ED_masklayer_frames_delete((MaskLayer *)ale->data);

View File

@ -685,7 +685,13 @@ static void node_update_basis_from_declaration(
/* Round the socket location to stop it from jiggling. */
item.runtime->location_y = round(locy + NODE_DYS);
if (!is_collapsed) {
locy -= NODE_ITEM_SPACING_Y / 2; /* Space at bottom of panel header. */
}
item.runtime->max_content_y = item.runtime->min_content_y = round(locy);
if (!is_collapsed) {
locy -= NODE_ITEM_SPACING_Y; /* Space at top of panel contents. */
}
}
else if (item.is_valid_socket()) {
if (item.input) {
@ -702,7 +708,7 @@ static void node_update_basis_from_declaration(
else {
/* Space between items. */
if (!is_first && item.input->is_visible()) {
locy -= NODE_SOCKDY;
locy -= NODE_ITEM_SPACING_Y;
}
}
}
@ -715,7 +721,7 @@ static void node_update_basis_from_declaration(
else {
/* Space between items. */
if (!is_first && item.output->is_visible()) {
locy -= NODE_SOCKDY;
locy -= NODE_ITEM_SPACING_Y;
}
}
}
@ -739,8 +745,14 @@ static void node_update_basis_from_declaration(
/* Incomplete panel, continue adding items. */
break;
}
/* Finalize the vertical extent of the content. */
top_panel.runtime->min_content_y = round(locy - NODE_DYS / 4);
if (!top_panel.is_collapsed) {
/* Finalize the vertical extent of the content. */
locy -= 2 * NODE_ITEM_SPACING_Y; /* Space at bottom of panel contents. */
top_panel.runtime->min_content_y = round(locy);
locy -= NODE_ITEM_SPACING_Y / 2; /* Space at top of next panel header. */
}
/* Close panel and continue checking parent. */
panel_updates.pop();
}
@ -779,7 +791,7 @@ static void node_update_basis_from_socket_lists(
if (node_update_basis_socket(C, ntree, node, nullptr, socket, block, locx, locy)) {
if (socket->next) {
locy -= NODE_SOCKDY;
locy -= NODE_ITEM_SPACING_Y;
}
add_output_space = true;
}
@ -798,7 +810,7 @@ static void node_update_basis_from_socket_lists(
if (node_update_basis_socket(C, ntree, node, socket, nullptr, block, locx, locy)) {
if (socket->next) {
locy -= NODE_SOCKDY;
locy -= NODE_ITEM_SPACING_Y;
}
}
}
@ -2660,12 +2672,7 @@ static void node_draw_basis(const bContext &C,
}
/* Shadow. */
if (!ELEM(node.type,
GEO_NODE_SIMULATION_INPUT,
GEO_NODE_SIMULATION_OUTPUT,
GEO_NODE_REPEAT_INPUT,
GEO_NODE_REPEAT_OUTPUT))
{
if (!bke::all_zone_node_types().contains(node.type)) {
node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
}
@ -2974,12 +2981,8 @@ static void node_draw_basis(const bContext &C,
else if (bke::node_type_is_undefined(&node)) {
UI_GetThemeColor4fv(TH_REDALERT, color_outline);
}
else if (ELEM(node.type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_SIMULATION_OUTPUT)) {
UI_GetThemeColor4fv(TH_NODE_ZONE_SIMULATION, color_outline);
color_outline[3] = 1.0f;
}
else if (ELEM(node.type, GEO_NODE_REPEAT_INPUT, GEO_NODE_REPEAT_OUTPUT)) {
UI_GetThemeColor4fv(TH_NODE_ZONE_REPEAT, color_outline);
else if (const bke::bNodeZoneType *zone_type = bke::zone_type_by_node_type(node.type)) {
UI_GetThemeColor4fv(zone_type->theme_id, color_outline);
color_outline[3] = 1.0f;
}
else {
@ -3718,10 +3721,7 @@ static void node_draw_zones(TreeDrawContext & /*tree_draw_ctx*/,
const auto get_theme_id = [&](const int zone_i) {
const bNode *node = zones->zones[zone_i]->output_node;
if (node->type == GEO_NODE_SIMULATION_OUTPUT) {
return TH_NODE_ZONE_SIMULATION;
}
return TH_NODE_ZONE_REPEAT;
return bke::zone_type_by_node_type(node->type)->theme_id;
};
const uint pos = GPU_vertformat_attr_add(

View File

@ -1292,37 +1292,21 @@ void remap_node_pairing(bNodeTree &dst_tree, const Map<const bNode *, bNode *> &
* so we have to build a map first to find copied output nodes in the new tree. */
Map<int32_t, bNode *> dst_output_node_map;
for (const auto &item : node_map.items()) {
if (ELEM(item.key->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_REPEAT_OUTPUT)) {
if (bke::all_zone_output_node_types().contains(item.key->type)) {
dst_output_node_map.add_new(item.key->identifier, item.value);
}
}
for (bNode *dst_node : node_map.values()) {
switch (dst_node->type) {
case GEO_NODE_SIMULATION_INPUT: {
NodeGeometrySimulationInput *data = static_cast<NodeGeometrySimulationInput *>(
dst_node->storage);
if (const bNode *output_node = dst_output_node_map.lookup_default(data->output_node_id,
nullptr)) {
data->output_node_id = output_node->identifier;
}
else {
data->output_node_id = 0;
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
}
break;
if (bke::all_zone_input_node_types().contains(dst_node->type)) {
const bke::bNodeZoneType &zone_type = *bke::zone_type_by_node_type(dst_node->type);
int &output_node_id = zone_type.get_corresponding_output_id(*dst_node);
if (const bNode *output_node = dst_output_node_map.lookup_default(output_node_id, nullptr)) {
output_node_id = output_node->identifier;
}
case GEO_NODE_REPEAT_INPUT: {
NodeGeometryRepeatInput *data = static_cast<NodeGeometryRepeatInput *>(dst_node->storage);
if (const bNode *output_node = dst_output_node_map.lookup_default(data->output_node_id,
nullptr)) {
data->output_node_id = output_node->identifier;
}
else {
data->output_node_id = 0;
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
}
break;
else {
output_node_id = 0;
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
}
}
}

View File

@ -148,31 +148,15 @@ static void remap_pairing(bNodeTree &dst_tree,
const Map<int32_t, int32_t> &identifier_map)
{
for (bNode *dst_node : nodes) {
switch (dst_node->type) {
case GEO_NODE_SIMULATION_INPUT: {
NodeGeometrySimulationInput *data = static_cast<NodeGeometrySimulationInput *>(
dst_node->storage);
if (data->output_node_id == 0) {
continue;
}
data->output_node_id = identifier_map.lookup_default(data->output_node_id, 0);
if (data->output_node_id == 0) {
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
}
break;
if (bke::all_zone_input_node_types().contains(dst_node->type)) {
const bke::bNodeZoneType &zone_type = *bke::zone_type_by_node_type(dst_node->type);
int &output_node_id = zone_type.get_corresponding_output_id(*dst_node);
if (output_node_id == 0) {
continue;
}
case GEO_NODE_REPEAT_INPUT: {
NodeGeometryRepeatInput *data = static_cast<NodeGeometryRepeatInput *>(dst_node->storage);
if (data->output_node_id == 0) {
continue;
}
data->output_node_id = identifier_map.lookup_default(data->output_node_id, 0);
if (data->output_node_id == 0) {
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
}
break;
output_node_id = identifier_map.lookup_default(output_node_id, 0);
if (output_node_id == 0) {
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
}
}
}
@ -788,58 +772,29 @@ static bool node_group_make_test_selected(bNodeTree &ntree,
return false;
}
}
/* Check if simulation zone pairs are fully selected.
* Simulation input or output nodes can only be grouped together with the paired node.
*/
for (bNode *input_node : ntree.nodes_by_type("GeometryNodeSimulationInput")) {
const NodeGeometrySimulationInput &input_data =
*static_cast<const NodeGeometrySimulationInput *>(input_node->storage);
if (bNode *output_node = ntree.node_by_id(input_data.output_node_id)) {
const bool input_selected = nodes_to_group.contains(input_node);
const bool output_selected = nodes_to_group.contains(output_node);
if (input_selected && !output_selected) {
BKE_reportf(
&reports,
RPT_WARNING,
"Can not add simulation input node '%s' to a group without its paired output '%s'",
input_node->name,
output_node->name);
return false;
}
if (output_selected && !input_selected) {
BKE_reportf(
&reports,
RPT_WARNING,
"Can not add simulation output node '%s' to a group without its paired input '%s'",
output_node->name,
input_node->name);
return false;
}
}
}
for (bNode *input_node : ntree.nodes_by_type("GeometryNodeRepeatInput")) {
const NodeGeometryRepeatInput &input_data = *static_cast<const NodeGeometryRepeatInput *>(
input_node->storage);
if (bNode *output_node = ntree.node_by_id(input_data.output_node_id)) {
const bool input_selected = nodes_to_group.contains(input_node);
const bool output_selected = nodes_to_group.contains(output_node);
if (input_selected && !output_selected) {
BKE_reportf(&reports,
RPT_WARNING,
"Can not add repeat input node '%s' to a group without its paired output '%s'",
input_node->name,
output_node->name);
return false;
}
if (output_selected && !input_selected) {
BKE_reportf(&reports,
RPT_WARNING,
"Can not add repeat output node '%s' to a group without its paired input '%s'",
output_node->name,
input_node->name);
return false;
/* Check if zone pairs are fully selected.
* Zone input or output nodes can only be grouped together with the paired node. */
for (const bke::bNodeZoneType *zone_type : bke::all_zone_types()) {
for (bNode *input_node : ntree.nodes_by_type(zone_type->input_idname)) {
if (bNode *output_node = zone_type->get_corresponding_output(ntree, *input_node)) {
const bool input_selected = nodes_to_group.contains(input_node);
const bool output_selected = nodes_to_group.contains(output_node);
if (input_selected && !output_selected) {
BKE_reportf(&reports,
RPT_WARNING,
"Can not add zone input node '%s' to a group without its paired output '%s'",
input_node->name,
output_node->name);
return false;
}
if (output_selected && !input_selected) {
BKE_reportf(&reports,
RPT_WARNING,
"Can not add zone output node '%s' to a group without its paired input '%s'",
output_node->name,
input_node->name);
return false;
}
}
}
}

View File

@ -139,7 +139,7 @@ ENUM_OPERATORS(NodeResizeDirection, NODE_RESIZE_LEFT);
#define BASIS_RAD (0.2f * U.widget_unit)
#define NODE_DYS (U.widget_unit / 2)
#define NODE_DY U.widget_unit
#define NODE_SOCKDY (0.1f * U.widget_unit)
#define NODE_ITEM_SPACING_Y (0.1f * U.widget_unit)
#define NODE_WIDTH(node) (node.width * UI_SCALE_FAC)
#define NODE_HEIGHT(node) (node.height * UI_SCALE_FAC)
#define NODE_MARGIN_X (1.2f * U.widget_unit)

View File

@ -315,25 +315,15 @@ void node_deselect_all_output_sockets(bNodeTree &node_tree, const bool deselect_
void node_select_paired(bNodeTree &node_tree)
{
for (bNode *input_node : node_tree.nodes_by_type("GeometryNodeSimulationInput")) {
const auto *storage = static_cast<const NodeGeometrySimulationInput *>(input_node->storage);
if (bNode *output_node = node_tree.node_by_id(storage->output_node_id)) {
if (input_node->flag & NODE_SELECT) {
output_node->flag |= NODE_SELECT;
}
if (output_node->flag & NODE_SELECT) {
input_node->flag |= NODE_SELECT;
}
}
}
for (bNode *input_node : node_tree.nodes_by_type("GeometryNodeRepeatInput")) {
const auto *storage = static_cast<const NodeGeometryRepeatInput *>(input_node->storage);
if (bNode *output_node = node_tree.node_by_id(storage->output_node_id)) {
if (input_node->flag & NODE_SELECT) {
output_node->flag |= NODE_SELECT;
}
if (output_node->flag & NODE_SELECT) {
input_node->flag |= NODE_SELECT;
for (const bke::bNodeZoneType *zone_type : bke::all_zone_types()) {
for (bNode *input_node : node_tree.nodes_by_type(zone_type->input_idname)) {
if (bNode *output_node = zone_type->get_corresponding_output(node_tree, *input_node)) {
if (input_node->flag & NODE_SELECT) {
output_node->flag |= NODE_SELECT;
}
if (output_node->flag & NODE_SELECT) {
input_node->flag |= NODE_SELECT;
}
}
}
}

View File

@ -177,8 +177,7 @@ static bool grease_pencil_layer_apply_trans_data(GreasePencil &grease_pencil,
if (canceled && duplicate) {
/* Duplicates were done, so we need to delete the corresponding duplicate drawings. */
for (const GreasePencilFrame &duplicate_frame : trans_data.temp_frames_buffer.values()) {
GreasePencilDrawingBase *drawing_base = grease_pencil.drawings(
duplicate_frame.drawing_index);
GreasePencilDrawingBase *drawing_base = grease_pencil.drawing(duplicate_frame.drawing_index);
if (drawing_base->type == GP_DRAWING) {
reinterpret_cast<GreasePencilDrawing *>(drawing_base)->wrap().remove_user();
}

View File

@ -53,7 +53,7 @@
#include "MEM_guardedalloc.h"
#include "RE_pipeline.h"
#include "render_types.h"
#include "intern/render_types.h"
#include "lineart_intern.h"

View File

@ -106,7 +106,9 @@ int main(int argc, const char *argv[])
};
blender::Vector<NamedBackend> backends_to_validate;
#ifdef WITH_OPENGL_BACKEND
backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL});
#endif
#ifdef WITH_METAL_BACKEND
backends_to_validate.append({"Metal", GPU_BACKEND_METAL});
#endif

View File

@ -247,13 +247,34 @@ void MTLStorageBuf::clear(uint32_t clear_value)
}
}
void MTLStorageBuf::copy_sub(VertBuf * /*src_*/,
uint /*dst_offset*/,
uint /*src_offset*/,
uint /*copy_size*/)
void MTLStorageBuf::copy_sub(VertBuf *src_, uint dst_offset, uint src_offset, uint copy_size)
{
/* TODO(Metal): Support Copy sub operation. */
MTL_LOG_WARNING("MTLStorageBuf::copy_sub not yet supported.");
MTLVertBuf *src = static_cast<MTLVertBuf *>(src_);
MTLStorageBuf *dst = this;
if (dst->metal_buffer_ == nullptr) {
dst->init();
}
if (src->vbo_ == nullptr) {
src->bind();
}
/* Fetch active context. */
MTLContext *ctx = static_cast<MTLContext *>(unwrap(GPU_context_active_get()));
BLI_assert(ctx);
/* Fetch Metal buffers. */
id<MTLBuffer> src_buf = src->vbo_->get_metal_buffer();
id<MTLBuffer> dst_buf = dst->metal_buffer_->get_metal_buffer();
BLI_assert(src_buf != nil);
BLI_assert(dst_buf != nil);
id<MTLBlitCommandEncoder> blit_encoder = ctx->main_command_buffer.ensure_begin_blit_encoder();
[blit_encoder copyFromBuffer:src_buf
sourceOffset:src_offset
toBuffer:dst_buf
destinationOffset:dst_offset
size:copy_size];
}
void MTLStorageBuf::read(void *data)

View File

@ -25,7 +25,7 @@ class MTLVertBuf : public VertBuf {
friend class MTLShader; /* For transform feedback. */
friend class MTLBatch;
friend class MTLContext; /* For transform feedback. */
friend class MTLStorageBuf; /* For bind as SSBO resource access. */
friend class MTLStorageBuf; /* For bind as SSBO resource access and copy sub. */
private:
/** Metal buffer allocation. **/

View File

@ -430,10 +430,10 @@ typedef struct GreasePencil {
blender::bke::greasepencil::LayerGroup &root_group();
/* Drawings read/write access. */
blender::Span<GreasePencilDrawingBase *> drawings() const;
blender::Span<const GreasePencilDrawingBase *> drawings() const;
blender::MutableSpan<GreasePencilDrawingBase *> drawings();
GreasePencilDrawingBase *drawings(int64_t index) const;
GreasePencilDrawingBase *drawings(int64_t index);
const GreasePencilDrawingBase *drawing(int64_t index) const;
GreasePencilDrawingBase *drawing(int64_t index);
blender::Span<const blender::bke::greasepencil::TreeNode *> nodes() const;
@ -538,7 +538,7 @@ typedef struct GreasePencil {
* drawing exists.
*/
blender::bke::greasepencil::Drawing *get_editable_drawing_at(
const blender::bke::greasepencil::Layer *layer, int frame_number) const;
const blender::bke::greasepencil::Layer *layer, int frame_number);
void foreach_visible_drawing(
const int frame,

View File

@ -3228,64 +3228,48 @@ static void rna_RepeatItem_color_get(PointerRNA *ptr, float *values)
ED_node_type_draw_color(socket_type_idname, values);
}
static PointerRNA rna_NodeGeometrySimulationInput_paired_output_get(PointerRNA *ptr)
static PointerRNA rna_Node_paired_output_get(PointerRNA *ptr)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
bNode *node = static_cast<bNode *>(ptr->data);
bNode *output_node = NOD_geometry_simulation_input_get_paired_output(ntree, node);
const blender::bke::bNodeZoneType &zone_type = *blender::bke::zone_type_by_node_type(node->type);
bNode *output_node = zone_type.get_corresponding_output(*ntree, *node);
PointerRNA r_ptr = RNA_pointer_create(&ntree->id, &RNA_Node, output_node);
return r_ptr;
}
static PointerRNA rna_NodeGeometryRepeatInput_paired_output_get(PointerRNA *ptr)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
bNode *node = static_cast<bNode *>(ptr->data);
NodeGeometryRepeatInput *storage = static_cast<NodeGeometryRepeatInput *>(node->storage);
bNode *output_node = ntree->node_by_id(storage->output_node_id);
PointerRNA r_ptr = RNA_pointer_create(&ntree->id, &RNA_Node, output_node);
return r_ptr;
}
static bool rna_GeometryNodeSimulationInput_pair_with_output(
static bool rna_Node_pair_with_output(
ID *id, bNode *node, bContext *C, ReportList *reports, bNode *output_node)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
if (!NOD_geometry_simulation_input_pair_with_output(ntree, node, output_node)) {
BKE_reportf(reports,
RPT_ERROR,
"Failed to pair simulation input node %s with output node %s",
node->name,
output_node->name);
const blender::bke::bNodeZoneType &zone_type = *blender::bke::zone_type_by_node_type(node->type);
if (output_node->type != zone_type.output_type) {
BKE_reportf(
reports,
RPT_ERROR,
"Can't pair zone input node %s with %s because it does not have the same zone type",
node->name,
output_node->name);
return false;
}
for (const bNode *other_input_node : ntree->nodes_by_type(zone_type.input_idname)) {
if (other_input_node != node) {
if (zone_type.get_corresponding_output(*ntree, *other_input_node) == output_node) {
BKE_reportf(reports,
RPT_ERROR,
"The output node %s is already paired with %s",
output_node->name,
other_input_node->name);
return false;
}
}
}
int &output_node_id = zone_type.get_corresponding_output_id(*node);
output_node_id = output_node->identifier;
BKE_ntree_update_tag_node_property(ntree, node);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
return true;
}
static bool rna_GeometryNodeRepeatInput_pair_with_output(
ID *id, bNode *node, bContext *C, ReportList *reports, bNode *output_node)
{
bNodeTree *ntree = (bNodeTree *)id;
if (!NOD_geometry_repeat_input_pair_with_output(ntree, node, output_node)) {
BKE_reportf(reports,
RPT_ERROR,
"Failed to pair repeat input node %s with output node %s",
node->name,
output_node->name);
return false;
}
BKE_ntree_update_tag_node_property(ntree, node);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
return true;
}
@ -8847,28 +8831,24 @@ static void def_geo_curve_set_handle_type(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
static void def_geo_simulation_input(StructRNA *srna)
static void def_common_zone_input(StructRNA *srna)
{
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
RNA_def_struct_sdna_from(srna, "NodeGeometrySimulationInput", "storage");
prop = RNA_def_property(srna, "paired_output", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Node");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, "rna_NodeGeometrySimulationInput_paired_output_get", nullptr, nullptr, nullptr);
RNA_def_property_pointer_funcs(prop, "rna_Node_paired_output_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(
prop, "Paired Output", "Simulation output node that this input node is paired with");
prop, "Paired Output", "Zone output node that this input node is paired with");
func = RNA_def_function(
srna, "pair_with_output", "rna_GeometryNodeSimulationInput_pair_with_output");
RNA_def_function_ui_description(func, "Pair a simulation input node with an output node.");
func = RNA_def_function(srna, "pair_with_output", "rna_Node_pair_with_output");
RNA_def_function_ui_description(func, "Pair a zone input node with an output node.");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "output_node", "GeometryNode", "Output Node", "Simulation output node to pair with");
func, "output_node", "GeometryNode", "Output Node", "Zone output node to pair with");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
/* return value */
parm = RNA_def_boolean(
@ -8876,33 +8856,18 @@ static void def_geo_simulation_input(StructRNA *srna)
RNA_def_function_return(func, parm);
}
static void def_geo_simulation_input(StructRNA *srna)
{
RNA_def_struct_sdna_from(srna, "NodeGeometrySimulationInput", "storage");
def_common_zone_input(srna);
}
static void def_geo_repeat_input(StructRNA *srna)
{
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
RNA_def_struct_sdna_from(srna, "NodeGeometryRepeatInput", "storage");
prop = RNA_def_property(srna, "paired_output", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Node");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, "rna_NodeGeometryRepeatInput_paired_output_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(
prop, "Paired Output", "Repeat output node that this input node is paired with");
func = RNA_def_function(
srna, "pair_with_output", "rna_GeometryNodeRepeatInput_pair_with_output");
RNA_def_function_ui_description(func, "Pair a repeat input node with an output node.");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "output_node", "GeometryNode", "Output Node", "Repeat output node to pair with");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
/* return value */
parm = RNA_def_boolean(
func, "result", false, "Result", "True if pairing the node was successful");
RNA_def_function_return(func, parm);
def_common_zone_input(srna);
}
static void rna_def_simulation_state_item(BlenderRNA *brna)

View File

@ -11,26 +11,6 @@ extern bNodeTreeType *ntreeType_Geometry;
void register_node_tree_type_geo();
void register_node_type_geo_custom_group(bNodeType *ntype);
/* -------------------------------------------------------------------- */
/** \name Simulation Input Node
* \{ */
bNode *NOD_geometry_simulation_input_get_paired_output(bNodeTree *node_tree,
const bNode *simulation_input_node);
/**
* Pair a simulation input node with an output node.
* \return True if pairing the node was successful.
*/
bool NOD_geometry_simulation_input_pair_with_output(const bNodeTree *node_tree,
bNode *simulation_input_node,
const bNode *simulation_output_node);
bool NOD_geometry_repeat_input_pair_with_output(const bNodeTree *node_tree,
bNode *repeat_input_node,
const bNode *repeat_output_node);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Simulation Output Node
* \{ */

View File

@ -96,29 +96,3 @@ static void node_register()
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_repeat_input_cc
bool NOD_geometry_repeat_input_pair_with_output(const bNodeTree *node_tree,
bNode *repeat_input_node,
const bNode *repeat_output_node)
{
namespace file_ns = blender::nodes::node_geo_repeat_input_cc;
BLI_assert(repeat_input_node->type == GEO_NODE_REPEAT_INPUT);
if (repeat_output_node->type != GEO_NODE_REPEAT_OUTPUT) {
return false;
}
/* Allow only one input paired to an output. */
for (const bNode *other_input_node : node_tree->nodes_by_type("GeometryNodeRepeatInput")) {
if (other_input_node != repeat_input_node) {
const NodeGeometryRepeatInput &other_storage = file_ns::node_storage(*other_input_node);
if (other_storage.output_node_id == repeat_output_node->identifier) {
return false;
}
}
}
NodeGeometryRepeatInput &storage = file_ns::node_storage(*repeat_input_node);
storage.output_node_id = repeat_output_node->identifier;
return true;
}

View File

@ -268,38 +268,3 @@ static void node_register()
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_simulation_input_cc
bNode *NOD_geometry_simulation_input_get_paired_output(bNodeTree *node_tree,
const bNode *simulation_input_node)
{
namespace file_ns = blender::nodes::node_geo_simulation_input_cc;
const NodeGeometrySimulationInput &data = file_ns::node_storage(*simulation_input_node);
return node_tree->node_by_id(data.output_node_id);
}
bool NOD_geometry_simulation_input_pair_with_output(const bNodeTree *node_tree,
bNode *sim_input_node,
const bNode *sim_output_node)
{
namespace file_ns = blender::nodes::node_geo_simulation_input_cc;
BLI_assert(sim_input_node->type == GEO_NODE_SIMULATION_INPUT);
if (sim_output_node->type != GEO_NODE_SIMULATION_OUTPUT) {
return false;
}
/* Allow only one input paired to an output. */
for (const bNode *other_input_node : node_tree->nodes_by_type("GeometryNodeSimulationInput")) {
if (other_input_node != sim_input_node) {
const NodeGeometrySimulationInput &other_storage = file_ns::node_storage(*other_input_node);
if (other_storage.output_node_id == sim_output_node->identifier) {
return false;
}
}
}
NodeGeometrySimulationInput &storage = file_ns::node_storage(*sim_input_node);
storage.output_node_id = sim_output_node->identifier;
return true;
}

View File

@ -16,6 +16,8 @@
#include "RNA_access.hh"
#include "UI_resources.hh"
static bool node_undefined_poll(const bNodeType * /*ntype*/,
const bNodeTree * /*nodetree*/,
const char ** /*r_disabled_hint*/)
@ -50,8 +52,54 @@ static void register_undefined_types()
blender::bke::NodeSocketTypeUndefined.output_link_limit = 0xFFF;
}
class SimulationZoneType : public blender::bke::bNodeZoneType {
public:
SimulationZoneType()
{
this->input_idname = "GeometryNodeSimulationInput";
this->output_idname = "GeometryNodeSimulationOutput";
this->input_type = GEO_NODE_SIMULATION_INPUT;
this->output_type = GEO_NODE_SIMULATION_OUTPUT;
this->theme_id = TH_NODE_ZONE_SIMULATION;
}
const int &get_corresponding_output_id(const bNode &input_bnode) const override
{
BLI_assert(input_bnode.type == this->input_type);
return static_cast<NodeGeometrySimulationInput *>(input_bnode.storage)->output_node_id;
}
};
class RepeatZoneType : public blender::bke::bNodeZoneType {
public:
RepeatZoneType()
{
this->input_idname = "GeometryNodeRepeatInput";
this->output_idname = "GeometryNodeRepeatOutput";
this->input_type = GEO_NODE_REPEAT_INPUT;
this->output_type = GEO_NODE_REPEAT_OUTPUT;
this->theme_id = TH_NODE_ZONE_REPEAT;
}
const int &get_corresponding_output_id(const bNode &input_bnode) const override
{
BLI_assert(input_bnode.type == this->input_type);
return static_cast<NodeGeometryRepeatInput *>(input_bnode.storage)->output_node_id;
}
};
static void register_zone_types()
{
static SimulationZoneType simulation_zone_type;
static RepeatZoneType repeat_zone_type;
blender::bke::register_node_zone_type(simulation_zone_type);
blender::bke::register_node_zone_type(repeat_zone_type);
}
void register_nodes()
{
register_zone_types();
register_undefined_types();
register_standard_node_socket_types();

View File

@ -692,6 +692,8 @@ static void wm_file_read_post(bContext *C,
CTX_wm_window_set(C, static_cast<wmWindow *>(wm->windows.first));
}
WM_cursor_wait(true);
#ifdef WITH_PYTHON
if (is_startup_file) {
/* On startup (by default), Python won't have been initialized.
@ -785,6 +787,12 @@ static void wm_file_read_post(bContext *C,
#endif
}
#ifndef WITH_HEADLESS
if (!G.background) {
WM_redraw_windows(C);
}
#endif /* WITH_HEADLESS */
/* report any errors.
* currently disabled if addons aren't yet loaded */
if (addons_loaded) {
@ -818,6 +826,8 @@ static void wm_file_read_post(bContext *C,
WM_toolsystem_init(C);
}
}
WM_cursor_wait(false);
}
static void wm_read_callback_pre_wrapper(bContext *C, const char *filepath)
@ -1002,6 +1012,26 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* so we can get the error message */
errno = 0;
#ifndef WITH_HEADLESS
if (!G.background) {
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
bool win_was_null = (win == nullptr);
if (win_was_null) {
win = static_cast<wmWindow *>(wm->windows.first);
CTX_wm_window_set(C, win);
}
if (win != nullptr) {
/* Redraw to remove any open menus. */
WM_redraw_windows(C);
if (win_was_null) {
CTX_wm_window_set(C, nullptr);
}
}
}
#endif /* WITH_HEADLESS */
WM_cursor_wait(true);
/* first try to append data from exotic file formats... */
@ -1067,6 +1097,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
bf_reports.duration.whole = PIL_check_seconds_timer() - bf_reports.duration.whole;
file_read_reports_finalize(&bf_reports);
WM_cursor_wait(true);
success = true;
}
}
@ -1171,6 +1202,8 @@ void wm_homefile_read_ex(bContext *C,
char filepath_startup[FILE_MAX];
char filepath_userdef[FILE_MAX];
WM_cursor_wait(true);
/* When 'app_template' is set:
* '{BLENDER_USER_CONFIG}/{app_template}' */
char app_template_system[FILE_MAX];
@ -1488,6 +1521,8 @@ void wm_homefile_read_ex(bContext *C,
CTX_wm_window_set(C, nullptr);
}
}
WM_cursor_wait(false);
}
void wm_homefile_read(bContext *C,