Realtime Compositor: Implement Anti-Aliasing node

This patch implements the Anti-Aliasing node by porting SMAA from
Workbench into a generic library that can be used by the realtime
compositor and potentially other users. SMAA was encapsulated in an
algorithm to prepare it for use by other nodes that require SMAA
support.

Pull Request: https://projects.blender.org/blender/blender/pulls/106114
This commit is contained in:
Omar Emara
2023-03-26 16:59:13 +02:00
committed by Omar Emara
parent 8c1090aeb0
commit 2f4a7d67b7
26 changed files with 414 additions and 23 deletions

View File

@@ -19,6 +19,7 @@ extern "C" {
/**
* Stored in R8G8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8G8_UNORM
* - GPU: GPU_RG8 texture format and GPU_DATA_UBYTE data format.
*/
extern const unsigned char areaTexBytes[];
@@ -30,6 +31,7 @@ extern const unsigned char areaTexBytes[];
/**
* Stored in R8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8_UNORM
* - GPU: GPU_R8 texture format and GPU_DATA_UBYTE data format.
*/
extern const unsigned char searchTexBytes[];

View File

@@ -131,6 +131,7 @@ set(SRC
intern/scanfill_utils.c
intern/serialize.cc
intern/session_uuid.c
intern/smaa_textures.c
intern/smallhash.c
intern/sort.c
intern/sort_utils.c
@@ -330,6 +331,7 @@ set(SRC
BLI_set_slots.hh
BLI_shared_cache.hh
BLI_simd.h
BLI_smaa_textures.h
BLI_smallhash.h
BLI_sort.h
BLI_sort.hh

View File

@@ -5,7 +5,7 @@
* 2013 Fernando Navarro <fernandn@microsoft.com>
* 2013 Diego Gutierrez <diegog@unizar.es> */
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
/* Don't re-wrap large data definitions. */
/* clang-format off */
@@ -13,6 +13,7 @@
/**
* Stored in R8G8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8G8_UNORM
* - GPU: GPU_RG8 texture format and GPU_DATA_UBYTE data format.
*/
const unsigned char areaTexBytes[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -14954,6 +14955,7 @@ const unsigned char areaTexBytes[] = {
/**
* Stored in R8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8_UNORM
* - GPU: GPU_R8 texture format and GPU_DATA_UBYTE data format.
*/
const unsigned char searchTexBytes[] = {
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,

View File

@@ -63,17 +63,21 @@ set(SRC
COM_utilities.hh
algorithms/intern/algorithm_parallel_reduction.cc
algorithms/intern/smaa.cc
algorithms/intern/symmetric_separable_blur.cc
algorithms/COM_algorithm_parallel_reduction.hh
algorithms/COM_algorithm_smaa.hh
algorithms/COM_algorithm_symmetric_separable_blur.hh
cached_resources/intern/morphological_distance_feather_weights.cc
cached_resources/intern/smaa_precomputed_textures.cc
cached_resources/intern/symmetric_blur_weights.cc
cached_resources/intern/symmetric_separable_blur_weights.cc
cached_resources/COM_cached_resource.hh
cached_resources/COM_morphological_distance_feather_weights.hh
cached_resources/COM_smaa_precomputed_textures.hh
cached_resources/COM_symmetric_blur_weights.hh
cached_resources/COM_symmetric_separable_blur_weights.hh
)
@@ -122,6 +126,9 @@ set(GLSL_SRC
shaders/compositor_read_pass.glsl
shaders/compositor_realize_on_domain.glsl
shaders/compositor_screen_lens_distortion.glsl
shaders/compositor_smaa_blending_weight_calculation.glsl
shaders/compositor_smaa_edge_detection.glsl
shaders/compositor_smaa_neighborhood_blending.glsl
shaders/compositor_split_viewer.glsl
shaders/compositor_symmetric_blur.glsl
shaders/compositor_symmetric_blur_variable_size.glsl
@@ -211,6 +218,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/infos/compositor_read_pass_info.hh
shaders/infos/compositor_realize_on_domain_info.hh
shaders/infos/compositor_screen_lens_distortion_info.hh
shaders/infos/compositor_smaa_info.hh
shaders/infos/compositor_split_viewer_info.hh
shaders/infos/compositor_symmetric_blur_info.hh
shaders/infos/compositor_symmetric_blur_variable_size_info.hh

View File

@@ -8,6 +8,7 @@
#include "BLI_math_vector_types.hh"
#include "COM_morphological_distance_feather_weights.hh"
#include "COM_smaa_precomputed_textures.hh"
#include "COM_symmetric_blur_weights.hh"
#include "COM_symmetric_separable_blur_weights.hh"
@@ -47,6 +48,9 @@ class StaticCacheManager {
Map<MorphologicalDistanceFeatherWeightsKey, std::unique_ptr<MorphologicalDistanceFeatherWeights>>
morphological_distance_feather_weights_;
/* A unique pointers that stores the cached SMAAPrecomputedTextures, if one is cached. */
std::unique_ptr<SMAAPrecomputedTextures> smaa_precomputed_textures_;
public:
/* Reset the cache manager by deleting the cached resources that are no longer needed because
* they weren't used in the last evaluation and prepare the remaining cached resources to track
@@ -72,6 +76,11 @@ class StaticCacheManager {
* cached for the next evaluation. */
MorphologicalDistanceFeatherWeights &get_morphological_distance_feather_weights(int type,
int radius);
/* Check if a cached SMAA precomputed texture exists, if it does, return it, otherwise, return
* a newly created one and store it in the manager. In both cases, tag the cached resource as
* needed to keep it cached for the next evaluation. */
SMAAPrecomputedTextures &get_smaa_precomputed_textures();
};
} // namespace blender::realtime_compositor

View File

@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "COM_context.hh"
#include "COM_result.hh"
namespace blender::realtime_compositor {
/* Anti-alias the given input using the SMAA algorithm and write the result into the given output.
* See the SMAA_THRESHOLD, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR, and SMAA_CORNER_ROUNDING defines
* in gpu_shader_smaa_lib.glsl for information on the parameters. */
void smaa(Context &context,
Result &input,
Result &output,
float threshold,
float local_contrast_adaptation_factor,
int corner_rounding);
} // namespace blender::realtime_compositor

View File

@@ -0,0 +1,109 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "COM_context.hh"
#include "COM_utilities.hh"
#include "COM_algorithm_smaa.hh"
#include "COM_smaa_precomputed_textures.hh"
namespace blender::realtime_compositor {
static Result detect_edges(Context &context,
Result &input,
float threshold,
float local_contrast_adaptation_factor)
{
GPUShader *shader = context.shader_manager().get("compositor_smaa_edge_detection");
GPU_shader_bind(shader);
GPU_shader_uniform_1f(shader, "smaa_threshold", threshold);
GPU_shader_uniform_1f(
shader, "smaa_local_contrast_adaptation_factor", local_contrast_adaptation_factor);
GPU_texture_filter_mode(input.texture(), true);
input.bind_as_texture(shader, "input_tx");
Result edges = Result::Temporary(ResultType::Color, context.texture_pool());
edges.allocate_texture(input.domain());
edges.bind_as_image(shader, "edges_img");
compute_dispatch_threads_at_least(shader, input.domain().size);
GPU_shader_unbind();
input.unbind_as_texture();
edges.unbind_as_image();
return edges;
}
static Result calculate_blending_weights(Context &context, Result &edges, int corner_rounding)
{
GPUShader *shader = context.shader_manager().get("compositor_smaa_blending_weight_calculation");
GPU_shader_bind(shader);
GPU_shader_uniform_1i(shader, "smaa_corner_rounding", corner_rounding);
GPU_texture_filter_mode(edges.texture(), true);
edges.bind_as_texture(shader, "edges_tx");
const SMAAPrecomputedTextures &smaa_precomputed_textures =
context.cache_manager().get_smaa_precomputed_textures();
smaa_precomputed_textures.bind_area_texture(shader, "area_tx");
smaa_precomputed_textures.bind_search_texture(shader, "search_tx");
Result weights = Result::Temporary(ResultType::Color, context.texture_pool());
weights.allocate_texture(edges.domain());
weights.bind_as_image(shader, "weights_img");
compute_dispatch_threads_at_least(shader, edges.domain().size);
GPU_shader_unbind();
edges.unbind_as_texture();
smaa_precomputed_textures.unbind_area_texture();
smaa_precomputed_textures.unbind_search_texture();
weights.unbind_as_image();
return weights;
}
static void blend_neighborhood(Context &context, Result &input, Result &weights, Result &output)
{
GPUShader *shader = context.shader_manager().get("compositor_smaa_neighborhood_blending");
GPU_shader_bind(shader);
GPU_texture_filter_mode(input.texture(), true);
input.bind_as_texture(shader, "input_tx");
GPU_texture_filter_mode(weights.texture(), true);
weights.bind_as_texture(shader, "weights_tx");
output.allocate_texture(input.domain());
output.bind_as_image(shader, "output_img");
compute_dispatch_threads_at_least(shader, input.domain().size);
GPU_shader_unbind();
input.unbind_as_texture();
weights.unbind_as_texture();
output.unbind_as_image();
}
void smaa(Context &context,
Result &input,
Result &output,
float threshold,
float local_contrast_adaptation_factor,
int corner_rounding)
{
Result edges = detect_edges(context, input, threshold, local_contrast_adaptation_factor);
Result weights = calculate_blending_weights(context, edges, corner_rounding);
edges.release();
blend_neighborhood(context, input, weights, output);
weights.release();
}
} // namespace blender::realtime_compositor

View File

@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "COM_cached_resource.hh"
namespace blender::realtime_compositor {
/* -------------------------------------------------------------------------------------------------
* SMAA Precomputed Textures.
*
* A cached resource that caches the precomputed textures needed by the SMAA algorithm. The
* precomputed textures are constants, so this is a parameterless cached resource. */
class SMAAPrecomputedTextures : public CachedResource {
private:
GPUTexture *search_texture_ = nullptr;
GPUTexture *area_texture_ = nullptr;
public:
SMAAPrecomputedTextures();
~SMAAPrecomputedTextures();
void bind_search_texture(GPUShader *shader, const char *sampler_name) const;
void unbind_search_texture() const;
void bind_area_texture(GPUShader *shader, const char *sampler_name) const;
void unbind_area_texture() const;
};
} // namespace blender::realtime_compositor

View File

@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_smaa_textures.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "COM_smaa_precomputed_textures.hh"
namespace blender::realtime_compositor {
SMAAPrecomputedTextures::SMAAPrecomputedTextures()
{
search_texture_ = GPU_texture_create_2d("SMAA Search",
SEARCHTEX_WIDTH,
SEARCHTEX_HEIGHT,
1,
GPU_R8,
GPU_TEXTURE_USAGE_SHADER_READ,
nullptr);
GPU_texture_update(search_texture_, GPU_DATA_UBYTE, searchTexBytes);
GPU_texture_filter_mode(search_texture_, true);
area_texture_ = GPU_texture_create_2d("SMAA Area",
AREATEX_WIDTH,
AREATEX_HEIGHT,
1,
GPU_RG8,
GPU_TEXTURE_USAGE_SHADER_READ,
nullptr);
GPU_texture_update(area_texture_, GPU_DATA_UBYTE, areaTexBytes);
GPU_texture_filter_mode(area_texture_, true);
}
SMAAPrecomputedTextures::~SMAAPrecomputedTextures()
{
GPU_texture_free(search_texture_);
GPU_texture_free(area_texture_);
}
void SMAAPrecomputedTextures::bind_search_texture(GPUShader *shader,
const char *sampler_name) const
{
const int texture_image_unit = GPU_shader_get_sampler_binding(shader, sampler_name);
GPU_texture_bind(search_texture_, texture_image_unit);
}
void SMAAPrecomputedTextures::unbind_search_texture() const
{
GPU_texture_unbind(search_texture_);
}
void SMAAPrecomputedTextures::bind_area_texture(GPUShader *shader, const char *sampler_name) const
{
const int texture_image_unit = GPU_shader_get_sampler_binding(shader, sampler_name);
GPU_texture_bind(area_texture_, texture_image_unit);
}
void SMAAPrecomputedTextures::unbind_area_texture() const
{
GPU_texture_unbind(area_texture_);
}
} // namespace blender::realtime_compositor

View File

@@ -5,6 +5,7 @@
#include "BLI_math_vector_types.hh"
#include "COM_morphological_distance_feather_weights.hh"
#include "COM_smaa_precomputed_textures.hh"
#include "COM_symmetric_blur_weights.hh"
#include "COM_symmetric_separable_blur_weights.hh"
@@ -22,6 +23,9 @@ void StaticCacheManager::reset()
symmetric_blur_weights_.remove_if([](auto item) { return !item.value->needed; });
symmetric_separable_blur_weights_.remove_if([](auto item) { return !item.value->needed; });
morphological_distance_feather_weights_.remove_if([](auto item) { return !item.value->needed; });
if (smaa_precomputed_textures_ && !smaa_precomputed_textures_->needed) {
smaa_precomputed_textures_.reset();
}
/* Second, reset the needed status of the remaining resources to false to ready them to track
* their needed status for the next evaluation. */
@@ -34,6 +38,9 @@ void StaticCacheManager::reset()
for (auto &value : morphological_distance_feather_weights_.values()) {
value->needed = false;
}
if (smaa_precomputed_textures_) {
smaa_precomputed_textures_->needed = false;
}
}
SymmetricBlurWeights &StaticCacheManager::get_symmetric_blur_weights(int type, float2 radius)
@@ -71,4 +78,14 @@ MorphologicalDistanceFeatherWeights &StaticCacheManager::
return weights;
}
SMAAPrecomputedTextures &StaticCacheManager::get_smaa_precomputed_textures()
{
if (!smaa_precomputed_textures_) {
smaa_precomputed_textures_ = std::make_unique<SMAAPrecomputedTextures>();
}
smaa_precomputed_textures_->needed = true;
return *smaa_precomputed_textures_;
}
} // namespace blender::realtime_compositor

View File

@@ -0,0 +1,19 @@
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
* to get the coordinates into the sampler's expected [0, 1] range. */
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(texture_size(edges_tx));
float4 offset[3];
vec2 pixel_coordinates;
SMAABlendingWeightCalculationVS(coordinates, pixel_coordinates, offset);
vec4 weights = SMAABlendingWeightCalculationPS(
coordinates, pixel_coordinates, offset, edges_tx, area_tx, search_tx, vec4(0.0));
imageStore(weights_img, texel, weights);
}

View File

@@ -0,0 +1,17 @@
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
* to get the coordinates into the sampler's expected [0, 1] range. */
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(texture_size(input_tx));
float4 offset[3];
SMAAEdgeDetectionVS(coordinates, offset);
vec2 edge = SMAALumaEdgeDetectionPS(coordinates, offset, input_tx);
imageStore(edges_img, texel, vec4(edge, vec2(0.0)));
}

View File

@@ -0,0 +1,17 @@
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
* to get the coordinates into the sampler's expected [0, 1] range. */
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(texture_size(input_tx));
vec4 offset;
SMAANeighborhoodBlendingVS(coordinates, offset);
vec4 result = SMAANeighborhoodBlendingPS(coordinates, offset, input_tx, weights_tx);
imageStore(output_img, texel, result);
}

View File

@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(compositor_smaa_edge_detection)
.local_group_size(16, 16)
.define("SMAA_GLSL_3")
.define("SMAA_LUMA_WEIGHT", "float4(1.0, 1.0, 1.0, 1.0)")
.define("SMAA_RT_METRICS",
"vec4(1.0 / vec2(textureSize(input_tx, 0)), vec2(textureSize(input_tx, 0)))")
.define("SMAA_THRESHOLD", "smaa_threshold")
.define("SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR", "smaa_local_contrast_adaptation_factor")
.push_constant(Type::FLOAT, "smaa_threshold")
.push_constant(Type::FLOAT, "smaa_local_contrast_adaptation_factor")
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "edges_img")
.compute_source("compositor_smaa_edge_detection.glsl")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(compositor_smaa_blending_weight_calculation)
.local_group_size(16, 16)
.define("SMAA_GLSL_3")
.define("SMAA_RT_METRICS",
"vec4(1.0 / vec2(textureSize(edges_tx, 0)), vec2(textureSize(edges_tx, 0)))")
.define("SMAA_CORNER_ROUNDING", "smaa_corner_rounding")
.push_constant(Type::INT, "smaa_corner_rounding")
.sampler(0, ImageType::FLOAT_2D, "edges_tx")
.sampler(1, ImageType::FLOAT_2D, "area_tx")
.sampler(2, ImageType::FLOAT_2D, "search_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "weights_img")
.compute_source("compositor_smaa_blending_weight_calculation.glsl")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(compositor_smaa_neighborhood_blending)
.local_group_size(16, 16)
.define("SMAA_GLSL_3")
.define("SMAA_RT_METRICS",
"vec4(1.0 / vec2(textureSize(input_tx, 0)), vec2(textureSize(input_tx, 0)))")
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.sampler(1, ImageType::FLOAT_2D, "weights_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.compute_source("compositor_smaa_neighborhood_blending.glsl")
.do_static_compilation(true);

View File

@@ -103,7 +103,6 @@ set(SRC
intern/draw_view.c
intern/draw_view_data.cc
intern/draw_volume.cc
intern/smaa_textures.c
engines/basic/basic_engine.c
engines/basic/basic_shader.c
engines/compositor/compositor_engine.cc
@@ -260,7 +259,6 @@ set(SRC
intern/draw_view.hh
intern/draw_view_data.h
intern/mesh_extractors/extract_mesh.hh
intern/smaa_textures.h
engines/basic/basic_engine.h
engines/basic/basic_private.h
engines/compositor/compositor_engine.h
@@ -554,7 +552,6 @@ set(GLSL_SRC
intern/shaders/common_math_lib.glsl
intern/shaders/common_pointcloud_lib.glsl
intern/shaders/common_shape_lib.glsl
intern/shaders/common_smaa_lib.glsl
intern/shaders/common_subdiv_custom_data_interp_comp.glsl
intern/shaders/common_subdiv_ibo_lines_comp.glsl
intern/shaders/common_subdiv_ibo_tris_comp.glsl

View File

@@ -9,7 +9,7 @@
#include "gpencil_engine.h"
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
{

View File

@@ -21,7 +21,6 @@ extern char datatoc_gpencil_vfx_frag_glsl[];
extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_fullscreen_vert_glsl[];
extern char datatoc_common_smaa_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
static struct {

View File

@@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@@ -20,7 +20,7 @@
#include "BLI_jitter_2d.h"
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
#include "workbench_private.h"

View File

@@ -3,7 +3,7 @@
#include "workbench_private.hh"
#include "BLI_jitter_2d.h"
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
namespace blender::workbench {

View File

@@ -437,6 +437,7 @@ set(GLSL_SRC
shaders/common/gpu_shader_math_matrix_lib.glsl
shaders/common/gpu_shader_math_rotation_lib.glsl
shaders/common/gpu_shader_math_vector_lib.glsl
shaders/common/gpu_shader_smaa_lib.glsl
shaders/common/gpu_shader_test_lib.glsl
shaders/common/gpu_shader_utildefines_lib.glsl

View File

@@ -774,14 +774,19 @@ float2 SMAALumaEdgeDetectionPS(float2 texcoord,
delta.xy = abs(L - float2(Lleft, Ltop));
float2 edges = step(threshold, delta.xy);
# ifndef SMAA_NO_DISCARD
# ifdef GPU_FRAGMENT_SHADER
# ifdef GPU_FRAGMENT_SHADER
# ifndef SMAA_NO_DISCARD
// Then discard if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0) {
discard;
return float2(0.0, 0.0);
}
# endif
# elif defined(GPU_COMPUTE_SHADER)
// Then return early if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0) {
return float2(0.0);
}
# endif
// Calculate right and bottom deltas:
@@ -802,9 +807,7 @@ float2 SMAALumaEdgeDetectionPS(float2 texcoord,
float finalDelta = max(maxDelta.x, maxDelta.y);
// Local contrast adaptation:
# if !defined(SHADER_API_OPENGL)
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
# endif
return edges;
}
@@ -882,9 +885,7 @@ float2 SMAAColorEdgeDetectionPS(float2 texcoord,
float finalDelta = max(maxDelta.x, maxDelta.y);
// Local contrast adaptation:
# if !defined(SHADER_API_OPENGL)
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
# endif
return edges;
}

View File

@@ -10,6 +10,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
#include "COM_algorithm_smaa.hh"
#include "COM_node_operation.hh"
#include "node_composite_util.hh"
@@ -18,9 +19,13 @@
namespace blender::nodes::node_composite_antialiasing_cc {
NODE_STORAGE_FUNCS(NodeAntiAliasingData)
static void cmp_node_antialiasing_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
b.add_input<decl::Color>(N_("Image"))
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
.compositor_domain_priority(0);
b.add_output<decl::Color>(N_("Image"));
}
@@ -54,8 +59,33 @@ class AntiAliasingOperation : public NodeOperation {
void execute() override
{
get_input("Image").pass_through(get_result("Image"));
context().set_info_message("Viewport compositor setup not fully supported");
smaa(context(),
get_input("Image"),
get_result("Image"),
get_threshold(),
get_local_contrast_adaptation_factor(),
get_corner_rounding());
}
/* Blender encodes the threshold in the [0, 1] range, while the SMAA algorithm expects it in
* the [0, 0.5] range. */
float get_threshold()
{
return node_storage(bnode()).threshold / 2.0f;
}
/* Blender encodes the local contrast adaptation factor in the [0, 1] range, while the SMAA
* algorithm expects it in the [0, 10] range. */
float get_local_contrast_adaptation_factor()
{
return node_storage(bnode()).threshold * 10.0f;
}
/* Blender encodes the corner rounding factor in the float [0, 1] range, while the SMAA algorithm
* expects it in the integer [0, 100] range. */
int get_corner_rounding()
{
return int(node_storage(bnode()).corner_rounding * 100.0f);
}
};
@@ -81,8 +111,6 @@ void register_node_type_cmp_antialiasing()
node_type_storage(
&ntype, "NodeAntiAliasingData", node_free_standard_storage, node_copy_standard_storage);
ntype.get_compositor_operation = file_ns::get_compositor_operation;
ntype.realtime_compositor_unsupported_message = N_(
"Node not supported in the Viewport compositor");
nodeRegisterType(&ntype);
}