UI: show recently selected items at the top of searches #110828
|
@ -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")
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
buildbot:
|
||||
gcc:
|
||||
version: '11.0.0'
|
||||
xcode:
|
||||
version: '15.0'
|
||||
cuda10:
|
||||
version: '10.1.243'
|
||||
cuda11:
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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 ----- */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. **/
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
* \{ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue