Blender V4.3
COM_SMAAOperation.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Jorge Jimenez <jorge@iryoku.com>
2 * SPDX-FileCopyrightText: 2013 Jose I. Echevarria <joseignacioechevarria@gmail.com>
3 * SPDX-FileCopyrightText: 2013 Belen Masia <bmasia@unizar.es>
4 * SPDX-FileCopyrightText: 2013 Fernando Navarro <fernandn@microsoft.com>
5 * SPDX-FileCopyrightText: 2013 Diego Gutierrez <diegog@unizar.es>
6 * SPDX-FileCopyrightText: 2019-2023 Blender Authors
7 *
8 * SPDX-License-Identifier: MIT AND GPL-2.0-or-later */
9
10#include "BLI_math_vector.h"
11#include "BLI_math_vector.hh"
12#include "BLI_smaa_textures.h"
13#include "BLI_span.hh"
14#include "BLI_task.hh"
15
17
18#include "COM_MemoryBuffer.h"
19#include "COM_SMAAOperation.h"
20
287/* ----------------------------------------------------------------------------
288 * Blender's Defines */
289
290#define SMAA_CUSTOM_SL
291#define SMAA_AREATEX_SELECT(sample) sample.xy()
292#define SMAA_SEARCHTEX_SELECT(sample) sample.x
293#define SMAATexture2D(tex) const MemoryBuffer *tex
294#define SMAATexturePass2D(tex) tex
295#define SMAASampleLevelZero(tex, coord) tex->texture_bilinear_extend(coord)
296#define SMAASampleLevelZeroPoint(tex, coord) tex->texture_bilinear_extend(coord)
297#define SMAASampleLevelZeroOffset(tex, coord, offset, size) \
298 tex->texture_bilinear_extend(coord + float2(offset) / float2(size))
299#define SMAASample(tex, coord) tex->texture_bilinear_extend(coord)
300#define SMAASamplePoint(tex, coord) tex->texture_nearest_extend(coord)
301#define SMAASamplePointOffset(tex, coord, offset, size) \
302 tex->texture_nearest_extend(coord + float2(offset) / float2(size))
303#define SMAASampleOffset(tex, coord, offset, size) \
304 tex->texture_bilinear_extend(coord + float2(offset) / float2(size))
305#define SMAA_FLATTEN
306#define SMAA_BRANCH
307#define lerp(a, b, t) math::interpolate(a, b, t)
308#define saturate(a) math::clamp(a, 0.0f, 1.0f)
309#define mad(a, b, c) (a * b + c)
310
311/* ----------------------------------------------------------------------------
312 * SMAA Presets */
313
319#if defined(SMAA_PRESET_LOW)
320# define SMAA_THRESHOLD 0.15f
321# define SMAA_MAX_SEARCH_STEPS 4
322# define SMAA_DISABLE_DIAG_DETECTION
323# define SMAA_DISABLE_CORNER_DETECTION
324#elif defined(SMAA_PRESET_MEDIUM)
325# define SMAA_THRESHOLD 0.1f
326# define SMAA_MAX_SEARCH_STEPS 8
327# define SMAA_DISABLE_DIAG_DETECTION
328# define SMAA_DISABLE_CORNER_DETECTION
329#elif defined(SMAA_PRESET_HIGH)
330# define SMAA_THRESHOLD 0.1f
331# define SMAA_MAX_SEARCH_STEPS 16
332# define SMAA_MAX_SEARCH_STEPS_DIAG 8
333# define SMAA_CORNER_ROUNDING 25
334#elif defined(SMAA_PRESET_ULTRA)
335# define SMAA_THRESHOLD 0.05f
336# define SMAA_MAX_SEARCH_STEPS 32
337# define SMAA_MAX_SEARCH_STEPS_DIAG 16
338# define SMAA_CORNER_ROUNDING 25
339#endif
340
341/* ----------------------------------------------------------------------------
342 * Configurable Defines */
343
356#ifndef SMAA_THRESHOLD
357# define SMAA_THRESHOLD 0.1f
358#endif
359
365#ifndef SMAA_DEPTH_THRESHOLD
366# define SMAA_DEPTH_THRESHOLD (0.1f * SMAA_THRESHOLD)
367#endif
368
379#ifndef SMAA_MAX_SEARCH_STEPS
380# define SMAA_MAX_SEARCH_STEPS 16
381#endif
382
395#ifndef SMAA_MAX_SEARCH_STEPS_DIAG
396# define SMAA_MAX_SEARCH_STEPS_DIAG 8
397#endif
398
406#ifndef SMAA_CORNER_ROUNDING
407# define SMAA_CORNER_ROUNDING 25
408#endif
409
418#ifndef SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR
419# define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0f
420#endif
421
436#ifndef SMAA_PREDICATION
437# define SMAA_PREDICATION 0
438#endif
439
446#ifndef SMAA_PREDICATION_THRESHOLD
447# define SMAA_PREDICATION_THRESHOLD 0.01f
448#endif
449
456#ifndef SMAA_PREDICATION_SCALE
457# define SMAA_PREDICATION_SCALE 2.0f
458#endif
459
465#ifndef SMAA_PREDICATION_STRENGTH
466# define SMAA_PREDICATION_STRENGTH 0.4f
467#endif
468
480#ifndef SMAA_REPROJECTION
481# define SMAA_REPROJECTION 0
482#endif
483
495#ifndef SMAA_REPROJECTION_WEIGHT_SCALE
496# define SMAA_REPROJECTION_WEIGHT_SCALE 30.0f
497#endif
498
503#ifndef SMAA_INCLUDE_VS
504# define SMAA_INCLUDE_VS 1
505#endif
506#ifndef SMAA_INCLUDE_PS
507# define SMAA_INCLUDE_PS 1
508#endif
509
510/* ----------------------------------------------------------------------------
511 * Texture Access Defines */
512
513#ifndef SMAA_AREATEX_SELECT
514# if defined(SMAA_HLSL_3)
515# define SMAA_AREATEX_SELECT(sample) sample.ra
516# else
517# define SMAA_AREATEX_SELECT(sample) sample.rg
518# endif
519#endif
520
521#ifndef SMAA_SEARCHTEX_SELECT
522# define SMAA_SEARCHTEX_SELECT(sample) sample.r
523#endif
524
525#ifndef SMAA_DECODE_VELOCITY
526# define SMAA_DECODE_VELOCITY(sample) sample.rg
527#endif
528
529/* ----------------------------------------------------------------------------
530 * Non-Configurable Defines */
531
532#define SMAA_AREATEX_MAX_DISTANCE 16
533#define SMAA_AREATEX_MAX_DISTANCE_DIAG 20
534#define SMAA_AREATEX_PIXEL_SIZE (1.0f / float2(160.0f, 560.0f))
535#define SMAA_AREATEX_SUBTEX_SIZE (1.0f / 7.0f)
536#define SMAA_SEARCHTEX_SIZE float2(66.0f, 33.0f)
537#define SMAA_SEARCHTEX_PACKED_SIZE float2(64.0f, 16.0f)
538#define SMAA_CORNER_ROUNDING_NORM (float(SMAA_CORNER_ROUNDING) / 100.0f)
539
540/* ----------------------------------------------------------------------------
541 * Porting Functions */
542
543#if defined(SMAA_HLSL_3)
544# define SMAATexture2D(tex) sampler2D tex
545# define SMAATexturePass2D(tex) tex
546# define SMAASampleLevelZero(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0))
547# define SMAASampleLevelZeroPoint(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0))
548/* clang-format off */
549# define SMAASampleLevelZeroOffset(tex, coord, offset) tex2Dlod(tex, float4(coord + offset * SMAA_RT_METRICS.xy, 0.0, 0.0))
550/* clang-format on */
551# define SMAASample(tex, coord) tex2D(tex, coord)
552# define SMAASamplePoint(tex, coord) tex2D(tex, coord)
553# define SMAASampleOffset(tex, coord, offset) tex2D(tex, coord + offset * SMAA_RT_METRICS.xy)
554# define SMAA_FLATTEN [flatten]
555# define SMAA_BRANCH [branch]
556#endif
557#if defined(SMAA_HLSL_4) || defined(SMAA_HLSL_4_1)
558SamplerState LinearSampler
559{
560 Filter = MIN_MAG_LINEAR_MIP_POINT;
561 AddressU = Clamp;
562 AddressV = Clamp;
563};
564SamplerState PointSampler
565{
566 Filter = MIN_MAG_MIP_POINT;
567 AddressU = Clamp;
568 AddressV = Clamp;
569};
570# define SMAATexture2D(tex) Texture2D tex
571# define SMAATexturePass2D(tex) tex
572# define SMAASampleLevelZero(tex, coord) tex.SampleLevel(LinearSampler, coord, 0)
573# define SMAASampleLevelZeroPoint(tex, coord) tex.SampleLevel(PointSampler, coord, 0)
574/* clang-format off */
575# define SMAASampleLevelZeroOffset(tex, coord, offset) tex.SampleLevel(LinearSampler, coord, 0, offset)
576/* clang-format on */
577# define SMAASample(tex, coord) tex.Sample(LinearSampler, coord)
578# define SMAASamplePoint(tex, coord) tex.Sample(PointSampler, coord)
579# define SMAASampleOffset(tex, coord, offset) tex.Sample(LinearSampler, coord, offset)
580# define SMAA_FLATTEN [flatten]
581# define SMAA_BRANCH [branch]
582# define SMAATexture2DMS2(tex) Texture2DMS<float4, 2> tex
583# define SMAALoad(tex, pos, sample) tex.Load(pos, sample)
584# if defined(SMAA_HLSL_4_1)
585# define SMAAGather(tex, coord) tex.Gather(LinearSampler, coord, 0)
586# endif
587#endif
588#if defined(SMAA_GLSL_3) || defined(SMAA_GLSL_4) || defined(GPU_METAL) || defined(GPU_VULKAN)
589# define SMAATexture2D(tex) sampler2D tex
590# define SMAATexturePass2D(tex) tex
591# define SMAASampleLevelZero(tex, coord) textureLod(tex, coord, 0.0)
592# define SMAASampleLevelZeroPoint(tex, coord) textureLod(tex, coord, 0.0)
593# define SMAASampleLevelZeroOffset(tex, coord, offset) textureLodOffset(tex, coord, 0.0, offset)
594# define SMAASample(tex, coord) texture(tex, coord)
595# define SMAASamplePoint(tex, coord) texture(tex, coord)
596# define SMAASampleOffset(tex, coord, offset) texture(tex, coord, offset)
597# define SMAA_FLATTEN
598# define SMAA_BRANCH
599# define lerp(a, b, t) mix(a, b, t)
600# define saturate(a) clamp(a, 0.0, 1.0)
601# if defined(SMAA_GLSL_4)
602# define SMAAGather(tex, coord) textureGather(tex, coord)
603# endif
604# if defined(SMAA_GLSL_4)
605# define mad(a, b, c) fma(a, b, c)
606# elif defined(GPU_VULKAN)
607/* NOTE(Vulkan) mad macro doesn't work, define each override as work-around. */
608vec4 mad(vec4 a, vec4 b, vec4 c)
609{
610 return fma(a, b, c);
611}
612vec3 mad(vec3 a, vec3 b, vec3 c)
613{
614 return fma(a, b, c);
615}
616vec2 mad(vec2 a, vec2 b, vec2 c)
617{
618 return fma(a, b, c);
619}
620float mad(float a, float b, float c)
621{
622 return fma(a, b, c);
623}
624# else
625# define mad(a, b, c) (a * b + c)
626# endif
627/* NOTE(Metal): Types already natively declared in MSL. */
628# ifndef GPU_METAL
629# define float2 vec2
630# define float3 vec3
631# define float4 vec4
632# define int2 ivec2
633# define int3 ivec3
634# define int4 ivec4
635# define bool2 bvec2
636# define bool3 bvec3
637# define bool4 bvec4
638# endif
639#endif
640
641/* clang-format off */
642#if !defined(SMAA_HLSL_3) && !defined(SMAA_HLSL_4) && !defined(SMAA_HLSL_4_1) && !defined(SMAA_GLSL_3) && !defined(SMAA_GLSL_4) && !defined(SMAA_CUSTOM_SL)
643# error you must define the shading language: SMAA_HLSL_*, SMAA_GLSL_* or SMAA_CUSTOM_SL
644#endif
645/* clang-format on */
646
647namespace blender::compositor {
648
649/* ----------------------------------------------------------------------------
650 * Misc functions */
651
655static void SMAAMovc(float2 cond, float2 &variable, float2 value)
656{
657 /* Use select function (select(genType A, genType B, genBType cond)). */
658 variable = math::interpolate(variable, value, cond);
659}
660
661static void SMAAMovc(float4 cond, float4 &variable, float4 value)
662{
663 /* Use select function (select(genType A, genType B, genBType cond)). */
664 variable = math::interpolate(variable, value, cond);
665}
666
667#if SMAA_INCLUDE_VS
668/* ----------------------------------------------------------------------------
669 * Vertex Shaders */
670
674static void SMAAEdgeDetectionVS(float2 texcoord, int2 size, float4 offset[3])
675{
676 offset[0] = float4(texcoord.xy(), texcoord.xy()) +
677 float4(-1.0f, 0.0f, 0.0f, -1.0f) / float4(size, size);
678 offset[1] = float4(texcoord.xy(), texcoord.xy()) +
679 float4(1.0f, 0.0f, 0.0f, 1.0f) / float4(size, size);
680 offset[2] = float4(texcoord.xy(), texcoord.xy()) +
681 float4(-2.0f, 0.0f, 0.0f, -2.0f) / float4(size, size);
682}
683
688 int2 size,
689 float2 &pixcoord,
690 float4 offset[3])
691{
692 pixcoord = texcoord * float2(size);
693
694 /* We will use these offsets for the searches later on (see @PSEUDO_GATHER4): */
695 offset[0] = float4(texcoord.xy(), texcoord.xy()) +
696 float4(-0.25f, -0.125f, 1.25f, -0.125f) / float4(size, size);
697 offset[1] = float4(texcoord.xy(), texcoord.xy()) +
698 float4(-0.125f, -0.25f, -0.125f, 1.25f) / float4(size, size);
699
700 /* And these for the searches, they indicate the ends of the loops: */
701 offset[2] = float4(offset[0].x, offset[0].z, offset[1].y, offset[1].w) +
702 (float4(-2.0f, 2.0f, -2.0f, 2.0f) * float(SMAA_MAX_SEARCH_STEPS)) /
703 float4(float2(size.x), float2(size.y));
704}
705
709static void SMAANeighborhoodBlendingVS(float2 texcoord, int2 size, float4 &offset)
710{
711 offset = float4(texcoord, texcoord) + float4(1.0f, 0.0f, 0.0f, 1.0f) / float4(size, size);
712}
713#endif /* SMAA_INCLUDE_VS */
714
722 float4 offset[3],
723 SMAATexture2D(colorTex),
725 SMAATexture2D(predicationTex),
726#endif
727 float edge_threshold,
728 float3 luminance_coefficients,
729 float local_contrast_adaptation_factor)
730{
731#if SMAA_PREDICATION
732 float2 threshold = SMAACalculatePredicatedThreshold(
733 texcoord, offset, SMAATexturePass2D(predicationTex));
734#else
735 /* Calculate the threshold: */
736 float2 threshold = float2(edge_threshold, edge_threshold);
737#endif
738
739 /* Calculate lumas: */
740 // float4 weights = float4(0.2126, 0.7152, 0.0722, 0.0);
741 float4 weights = float4(luminance_coefficients, 0.0f);
742 float L = math::dot(SMAASamplePoint(colorTex, texcoord), weights);
743
744 float Lleft = math::dot(SMAASamplePoint(colorTex, offset[0].xy()), weights);
745 float Ltop = math::dot(SMAASamplePoint(colorTex, offset[0].zw()), weights);
746
747 /* We do the usual threshold: */
748 float4 delta;
749 float2 delta_left_top = math::abs(L - float2(Lleft, Ltop));
750 delta.x = delta_left_top.x;
751 delta.y = delta_left_top.y;
752 float2 edges = math::step(threshold, delta.xy());
753
754 /* Then return early if there is no edge: */
755 if (math::dot(edges, float2(1.0f, 1.0f)) == 0.0f) {
756 return float2(0.0f);
757 }
758
759 /* Calculate right and bottom deltas: */
760 float Lright = math::dot(SMAASamplePoint(colorTex, offset[1].xy()), weights);
761 float Lbottom = math::dot(SMAASamplePoint(colorTex, offset[1].zw()), weights);
762 float2 delta_right_bottom = math::abs(L - float2(Lright, Lbottom));
763 delta.z = delta_right_bottom.x;
764 delta.w = delta_right_bottom.y;
765
766 /* Calculate the maximum delta in the direct neighborhood: */
767 float2 maxDelta = math::max(delta.xy(), delta.zw());
768
769 /* Calculate left-left and top-top deltas: */
770 float Lleftleft = math::dot(SMAASamplePoint(colorTex, offset[2].xy()), weights);
771 float Ltoptop = math::dot(SMAASamplePoint(colorTex, offset[2].zw()), weights);
772 float2 delta_left_left_top_top = math::abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop));
773 delta.z = delta_left_left_top_top.x;
774 delta.w = delta_left_left_top_top.y;
775
776 /* Calculate the final maximum delta: */
777 maxDelta = math::max(maxDelta.xy(), delta.zw());
778 float finalDelta = math::max(maxDelta.x, maxDelta.y);
779
780 /* Local contrast adaptation: */
781 edges *= math::step(finalDelta, local_contrast_adaptation_factor * delta.xy());
782
783 return edges;
784}
785
786/* ----------------------------------------------------------------------------
787 * Diagonal Search Functions */
788
789#if !defined(SMAA_DISABLE_DIAG_DETECTION)
790
795{
796 /* Bilinear access for fetching 'e' have a 0.25 offset, and we are
797 * interested in the R and G edges:
798 *
799 * +---G---+-------+
800 * | x o R x |
801 * +-------+-------+
802 *
803 * Then, if one of these edge is enabled:
804 * Red: `(0.75 * X + 0.25 * 1) => 0.25 or 1.0`
805 * Green: `(0.75 * 1 + 0.25 * X) => 0.75 or 1.0`
806 *
807 * This function will unpack the values `(mad + mul + round)`:
808 * wolframalpha.com: `round(x * abs(5 * x - 5 * 0.75))` plot 0 to 1
809 */
810 e.x = e.x * math::abs(5.0f * e.x - 5.0f * 0.75f);
811 return math::round(e);
812}
813
815{
816 e.x = e.x * math::abs(5.0f * e.x - 5.0f * 0.75f);
817 e.z = e.z * math::abs(5.0f * e.z - 5.0f * 0.75f);
818 return math::round(e);
819}
820
825 SMAATexture2D(edgesTex), float2 texcoord, float2 dir, int2 size, float2 &e)
826{
827 float4 coord = float4(texcoord, -1.0f, 1.0f);
828 float3 t = float3(1.0f / float2(size), 1.0f);
829 while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && coord.w > 0.9f) {
830 float3 increment = mad(t, float3(dir, 1.0f), coord.xyz());
831 coord.x = increment.x;
832 coord.y = increment.y;
833 coord.z = increment.z;
834 e = SMAASamplePoint(edgesTex, coord.xy()).xy();
835 coord.w = math::dot(e, float2(0.5f, 0.5f));
836 }
837 return coord.zw();
838}
839
841 SMAATexture2D(edgesTex), float2 texcoord, float2 dir, int2 size, float2 &e)
842{
843 float4 coord = float4(texcoord, -1.0f, 1.0f);
844 coord.x += 0.25f / size.x; /* See @SearchDiag2Optimization */
845 float3 t = float3(1.0f / float2(size), 1.0f);
846 while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && coord.w > 0.9f) {
847 float3 increment = mad(t, float3(dir, 1.0f), coord.xyz());
848 coord.x = increment.x;
849 coord.y = increment.y;
850 coord.z = increment.z;
851
852 /* @SearchDiag2Optimization */
853 /* Fetch both edges at once using bilinear filtering: */
854 e = SMAASampleLevelZero(edgesTex, coord.xy()).xy();
856
857 /* Non-optimized version: */
858 // e.g = SMAASampleLevelZero(edgesTex, coord.xy).g;
859 // e.r = SMAASampleLevelZeroOffset(edgesTex, coord.xy, int2(1, 0), size).r;
860
861 coord.w = math::dot(e, float2(0.5f, 0.5f));
862 }
863 return coord.zw();
864}
865
870static float2 SMAAAreaDiag(SMAATexture2D(areaTex), float2 dist, float2 e, float offset)
871{
872 float2 texcoord = mad(
874
875 /* We do a scale and bias for mapping to texel space: */
876 texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5f * SMAA_AREATEX_PIXEL_SIZE);
877
878 /* Diagonal areas are on the second half of the texture: */
879 texcoord.x += 0.5f;
880
881 /* Move to proper place, according to the sub-pixel offset: */
882 texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
883
884 /* Do it! */
885 return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord));
886}
887
892 SMAATexture2D(areaTex),
893 float2 texcoord,
894 float2 e,
895 float4 subsampleIndices,
896 int2 size)
897{
898 float2 weights = float2(0.0f, 0.0f);
899
900 /* Search for the line ends: */
901 float4 d;
902 float2 end;
903 if (e.x > 0.0f) {
904 float2 negative_diagonal = SMAASearchDiag1(
905 SMAATexturePass2D(edgesTex), texcoord, float2(-1.0f, 1.0f), size, end);
906 d.x = negative_diagonal.x;
907 d.z = negative_diagonal.y;
908 d.x += float(end.y > 0.9f);
909 }
910 else {
911 d.x = 0.0f;
912 d.z = 0.0f;
913 }
914 float2 positive_diagonal = SMAASearchDiag1(
915 SMAATexturePass2D(edgesTex), texcoord, float2(1.0, -1.0), size, end);
916 d.y = positive_diagonal.x;
917 d.w = positive_diagonal.y;
918
920 if (d.x + d.y > 2.0f) { /* `d.x + d.y + 1 > 3`. */
921 /* Fetch the crossing edges: */
922 float4 coords = float4(texcoord, texcoord) +
923 float4(-d.x + 0.25f, d.x, d.y, -d.y - 0.25f) / float4(size, size);
924 float4 c;
925 float2 left_edge = SMAASampleLevelZeroOffset(edgesTex, coords.xy(), int2(-1, 0), size).xy();
926 float2 right_edge = SMAASampleLevelZeroOffset(edgesTex, coords.zw(), int2(1, 0), size).xy();
927 c.x = left_edge.x;
928 c.y = left_edge.y;
929 c.z = right_edge.x;
930 c.w = right_edge.y;
931 float4 decoded_access = SMAADecodeDiagBilinearAccess(c);
932 c.y = decoded_access.x;
933 c.x = decoded_access.y;
934 c.w = decoded_access.z;
935 c.z = decoded_access.w;
936
937 /* Non-optimized version: */
938 // float4 coords = mad(float4(-d.x, d.x, d.y, -d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy);
939 // float4 c;
940 // c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0), size).g;
941 // c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, 0), size).r;
942 // c.z = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0), size).g;
943 // c.w = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, -1), size).r;
944
945 /* Merge crossing edges at each side into a single value: */
946 float2 cc = mad(float2(2.0f, 2.0f), float2(c.x, c.z), float2(c.y, c.w));
947
948 /* Remove the crossing edge if we didn't found the end of the line: */
949 SMAAMovc(math::step(0.9f, d.zw()), cc, float2(0.0f, 0.0f));
950
951 /* Fetch the areas for this line: */
952 weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy(), cc, subsampleIndices.z);
953 }
954
955 /* Search for the line ends: */
956 float2 negative_diagonal = SMAASearchDiag2(
957 SMAATexturePass2D(edgesTex), texcoord, float2(-1.0f, -1.0f), size, end);
958 d.x = negative_diagonal.x;
959 d.z = negative_diagonal.y;
960 if (SMAASamplePointOffset(edgesTex, texcoord, int2(1, 0), size).x > 0.0f) {
961 float2 positive_diagonal = SMAASearchDiag2(
962 SMAATexturePass2D(edgesTex), texcoord, float2(1.0f, 1.0f), size, end);
963 d.y = positive_diagonal.x;
964 d.w = positive_diagonal.y;
965 d.y += float(end.y > 0.9f);
966 }
967 else {
968 d.y = 0.0f;
969 d.w = 0.0f;
970 }
971
973 if (d.x + d.y > 2.0f) { /* `d.x + d.y + 1 > 3` */
974 /* Fetch the crossing edges: */
975 float4 coords = float4(texcoord, texcoord) + float4(-d.x, -d.x, d.y, d.y) / float4(size, size);
976 float4 c;
977 c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy(), int2(-1, 0), size).y;
978 c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy(), int2(0, -1), size).x;
979 float2 left_edge = SMAASampleLevelZeroOffset(edgesTex, coords.zw(), int2(1, 0), size).xy();
980 c.z = left_edge.y;
981 c.w = left_edge.x;
982 float2 cc = mad(float2(2.0f, 2.0f), float2(c.x, c.z), float2(c.y, c.w));
983
984 /* Remove the crossing edge if we didn't found the end of the line: */
985 SMAAMovc(math::step(0.9f, d.zw()), cc, float2(0.0f, 0.0f));
986
987 /* Fetch the areas for this line: */
988 float2 area = SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy(), cc, subsampleIndices.w).xy();
989 weights.x += area.y;
990 weights.y += area.x;
991 }
992
993 return weights;
994}
995#endif
996
997/* ----------------------------------------------------------------------------
998 * Horizontal/Vertical Search Functions */
999
1006static float SMAASearchLength(SMAATexture2D(searchTex), float2 e, float offset)
1007{
1008 /* The texture is flipped vertically, with left and right cases taking half
1009 * of the space horizontally: */
1010 float2 scale = SMAA_SEARCHTEX_SIZE * float2(0.5f, -1.0f);
1011 float2 bias = SMAA_SEARCHTEX_SIZE * float2(offset, 1.0f);
1012
1013 /* Scale and bias to access texel centers: */
1014 scale += float2(-1.0f, 1.0f);
1015 bias += float2(0.5f, -0.5f);
1016
1017 /* Convert from pixel coordinates to texcoords:
1018 * (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped). */
1019 scale *= 1.0f / SMAA_SEARCHTEX_PACKED_SIZE;
1020 bias *= 1.0f / SMAA_SEARCHTEX_PACKED_SIZE;
1021
1022 /* Lookup the search texture: */
1023 return SMAA_SEARCHTEX_SELECT(SMAASampleLevelZero(searchTex, mad(scale, e, bias)));
1024}
1025
1029static float SMAASearchXLeft(
1030 SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
1031{
1039 float2 e = float2(0.0f, 1.0f);
1040 while (texcoord.x > end && e.y > 0.8281f && /* Is there some edge not activated? */
1041 e.x == 0.0f) /* Or is there a crossing edge that breaks the line? */
1042 {
1043 e = SMAASampleLevelZero(edgesTex, texcoord).xy();
1044 texcoord = texcoord - float2(2.0f, 0.0f) / float2(size);
1045 }
1046
1047 float offset = mad(
1048 -(255.0f / 127.0f), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0f), 3.25f);
1049 return texcoord.x + offset / size.x;
1050
1051 /* Non-optimized version:
1052 * We correct the previous (-0.25, -0.125) offset we applied: */
1053 // texcoord.x += 0.25 * SMAA_RT_METRICS.x;
1054
1055 /* The searches are bias by 1, so adjust the coords accordingly: */
1056 // texcoord.x += SMAA_RT_METRICS.x;
1057
1058 /* Disambiguate the length added by the last step: */
1059 // texcoord.x += 2.0 * SMAA_RT_METRICS.x; /* Undo last step. */
1060 // texcoord.x -= SMAA_RT_METRICS.x * (255.0 / 127.0) *
1061 // SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0);
1062 // return mad(SMAA_RT_METRICS.x, offset, texcoord.x);
1063}
1064
1065static float SMAASearchXRight(
1066 SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
1067{
1068 float2 e = float2(0.0f, 1.0f);
1069 while (texcoord.x < end && e.y > 0.8281f && /* Is there some edge not activated? */
1070 e.x == 0.0f) /* Or is there a crossing edge that breaks the line? */
1071 {
1072 e = SMAASampleLevelZero(edgesTex, texcoord).xy();
1073 texcoord = texcoord + float2(2.0f, 0.0f) / float2(size);
1074 }
1075 float offset = mad(
1076 -(255.0f / 127.0f), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.5f), 3.25f);
1077 return texcoord.x - offset / size.x;
1078}
1079
1080static float SMAASearchYUp(
1081 SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
1082{
1083 float2 e = float2(1.0f, 0.0f);
1084 while (texcoord.y > end && e.x > 0.8281f && /* Is there some edge not activated? */
1085 e.y == 0.0f) /* Or is there a crossing edge that breaks the line? */
1086 {
1087 e = SMAASampleLevelZero(edgesTex, texcoord).xy();
1088 texcoord = texcoord - float2(0.0f, 2.0f) / float2(size);
1089 }
1090 float2 flipped_edge = float2(e.y, e.x);
1091 float offset = mad(-(255.0f / 127.0f),
1092 SMAASearchLength(SMAATexturePass2D(searchTex), flipped_edge, 0.0f),
1093 3.25f);
1094 return texcoord.y + offset / size.y;
1095}
1096
1097static float SMAASearchYDown(
1098 SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
1099{
1100 float2 e = float2(1.0f, 0.0f);
1101 while (texcoord.y < end && e.x > 0.8281f && /* Is there some edge not activated? */
1102 e.y == 0.0f) /* Or is there a crossing edge that breaks the line? */
1103 {
1104 e = SMAASampleLevelZero(edgesTex, texcoord).xy();
1105 texcoord = texcoord + float2(0.0f, 2.0f) / float2(size);
1106 }
1107 float2 flipped_edge = float2(e.y, e.x);
1108 float offset = mad(-(255.0f / 127.0f),
1109 SMAASearchLength(SMAATexturePass2D(searchTex), flipped_edge, 0.5f),
1110 3.25f);
1111 return texcoord.y - offset / size.y;
1112}
1113
1118static float2 SMAAArea(SMAATexture2D(areaTex), float2 dist, float e1, float e2, float offset)
1119{
1120 /* Rounding prevents precision errors of bilinear filtering: */
1122 math::round(4.0f * float2(e1, e2)),
1123 dist);
1124
1125 /* We do a scale and bias for mapping to texel space: */
1126 texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5f * SMAA_AREATEX_PIXEL_SIZE);
1127
1128 /* Move to proper place, according to the sub-pixel offset: */
1129 texcoord.y = mad(SMAA_AREATEX_SUBTEX_SIZE, offset, texcoord.y);
1130
1131 /* Do it! */
1132 return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord));
1133}
1134
1135/* ----------------------------------------------------------------------------
1136 * Corner Detection Functions */
1137
1139 float2 &weights,
1140 float4 texcoord,
1141 float2 d,
1142 int2 size,
1143 int corner_rounding)
1144{
1145#if !defined(SMAA_DISABLE_CORNER_DETECTION)
1146 float2 leftRight = math::step(d, float2(d.y, d.x));
1147 float2 rounding = (1.0f - corner_rounding / 100.0f) * leftRight;
1148
1149 rounding /= leftRight.x + leftRight.y; /* Reduce blending for pixels in the center of a line. */
1150
1151 float2 factor = float2(1.0f, 1.0f);
1152 factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy(), int2(0, 1), size).x;
1153 factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw(), int2(1, 1), size).x;
1154 factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy(), int2(0, -2), size).x;
1155 factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw(), int2(1, -2), size).x;
1156
1157 weights *= saturate(factor);
1158#endif
1159}
1160
1162 float2 &weights,
1163 float4 texcoord,
1164 float2 d,
1165 int2 size,
1166 int corner_rounding)
1167{
1168#if !defined(SMAA_DISABLE_CORNER_DETECTION)
1169 float2 leftRight = math::step(d, float2(d.y, d.x));
1170 float2 rounding = (1.0f - corner_rounding / 100.0f) * leftRight;
1171
1172 rounding /= leftRight.x + leftRight.y;
1173
1174 float2 factor = float2(1.0f, 1.0f);
1175 factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy(), int2(1, 0), size).y;
1176 factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw(), int2(1, 1), size).y;
1177 factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy(), int2(-2, 0), size).y;
1178 factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw(), int2(-2, 1), size).y;
1179
1180 weights *= saturate(factor);
1181#endif
1182}
1183
1184/* ----------------------------------------------------------------------------
1185 * Blending Weight Calculation Pixel Shader (Second Pass) */
1186
1188 float2 pixcoord,
1189 float4 offset[3],
1190 MemoryBuffer *edgesTex,
1191 MemoryBuffer *areaTex,
1192 MemoryBuffer *searchTex,
1193 float4 subsampleIndices,
1194 int2 size,
1195 int corner_rounding)
1196{
1197 /* Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES. */
1198 float4 weights = float4(0.0f, 0.0f, 0.0f, 0.0f);
1199
1200 float2 e = SMAASamplePoint(edgesTex, texcoord).xy();
1201
1203 if (e.y > 0.0f) { /* Edge at north. */
1204#if !defined(SMAA_DISABLE_DIAG_DETECTION)
1205 /* Diagonals have both north and west edges, so searching for them in
1206 * one of the boundaries is enough. */
1207 float2 diagonal_weights = SMAACalculateDiagWeights(SMAATexturePass2D(edgesTex),
1208 SMAATexturePass2D(areaTex),
1209 texcoord,
1210 e,
1211 subsampleIndices,
1212 size);
1213
1214 weights.x = diagonal_weights.x;
1215 weights.y = diagonal_weights.y;
1216
1217 /* We give priority to diagonals, so if we find a diagonal we skip
1218 * horizontal/vertical processing. */
1220 if (weights.x == -weights.y) { /* `weights.x + weights.y == 0.0` */
1221#endif
1222
1223 float2 d;
1224
1225 /* Find the distance to the left: */
1226 float3 coords;
1227 coords.x = SMAASearchXLeft(SMAATexturePass2D(edgesTex),
1228 SMAATexturePass2D(searchTex),
1229 offset[0].xy(),
1230 offset[2].x,
1231 size);
1232 coords.y =
1233 offset[1].y; // offset[1].y = texcoord.y - 0.25 * SMAA_RT_METRICS.y (@CROSSING_OFFSET)
1234 d.x = coords.x;
1235
1236 /* Now fetch the left crossing edges, two at a time using bilinear
1237 * filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to
1238 * discern what value each edge has: */
1239 float e1 = SMAASampleLevelZero(edgesTex, coords.xy()).x;
1240
1241 /* Find the distance to the right: */
1242 coords.z = SMAASearchXRight(SMAATexturePass2D(edgesTex),
1243 SMAATexturePass2D(searchTex),
1244 offset[0].zw(),
1245 offset[2].y,
1246 size);
1247 d.y = coords.z;
1248
1249 /* We want the distances to be in pixel units (doing this here allows
1250 * better interleaving of arithmetic and memory accesses): */
1251 d = math::abs(math::round(mad(float2(size.x), d, -float2(pixcoord.x))));
1252
1253 /* SMAAArea below needs a sqrt, as the areas texture is compressed quadratically: */
1254 float2 sqrt_d = math::sqrt(d);
1255
1256 /* Fetch the right crossing edges: */
1257 float e2 =
1258 SMAASampleLevelZeroOffset(edgesTex, float2(coords.z, coords.y), int2(1, 0), size).x;
1259
1260 /* Ok, we know how this pattern looks like, now it is time for getting the actual area: */
1261 float2 area = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.y);
1262 weights.x = area.x;
1263 weights.y = area.y;
1264
1265 /* Fix corners: */
1266 coords.y = texcoord.y;
1267
1268 float2 corner_weight = weights.xy();
1270 corner_weight,
1271 float4(coords.xy(), coords.z, coords.y),
1272 d,
1273 size,
1274 corner_rounding);
1275 weights.x = corner_weight.x;
1276 weights.y = corner_weight.y;
1277
1278#if !defined(SMAA_DISABLE_DIAG_DETECTION)
1279 }
1280 else
1281 e.x = 0.0f; /* Skip vertical processing. */
1282#endif
1283 }
1284
1286 if (e.x > 0.0f) { /* Edge at west. */
1287 float2 d;
1288
1289 /* Find the distance to the top: */
1290 float3 coords;
1291 coords.y = SMAASearchYUp(SMAATexturePass2D(edgesTex),
1292 SMAATexturePass2D(searchTex),
1293 offset[1].xy(),
1294 offset[2].z,
1295 size);
1296 coords.x = offset[0].x; // offset[1].x = texcoord.x - 0.25 * SMAA_RT_METRICS.x;
1297 d.x = coords.y;
1298
1299 /* Fetch the top crossing edges: */
1300 float e1 = SMAASampleLevelZero(edgesTex, coords.xy()).y;
1301
1302 /* Find the distance to the bottom: */
1303 coords.z = SMAASearchYDown(SMAATexturePass2D(edgesTex),
1304 SMAATexturePass2D(searchTex),
1305 offset[1].zw(),
1306 offset[2].w,
1307 size);
1308 d.y = coords.z;
1309
1310 /* We want the distances to be in pixel units: */
1311 d = math::abs(math::round(mad(float2(size.y), d, -float2(pixcoord.y))));
1312
1313 /* SMAAArea below needs a sqrt, as the areas texture is compressed quadratically: */
1314 float2 sqrt_d = math::sqrt(d);
1315
1316 /* Fetch the bottom crossing edges: */
1317 float e2 = SMAASampleLevelZeroOffset(edgesTex, float2(coords.x, coords.z), int2(0, 1), size).y;
1318
1319 /* Get the area for this direction: */
1320 float2 area = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.x);
1321 weights.z = area.x;
1322 weights.w = area.y;
1323
1324 /* Fix corners: */
1325 coords.x = texcoord.x;
1326
1327 float2 corner_weight = weights.zw();
1329 corner_weight,
1330 float4(coords.xy(), coords.x, coords.z),
1331 d,
1332 size,
1333 corner_rounding);
1334 weights.z = corner_weight.x;
1335 weights.w = corner_weight.y;
1336 }
1337
1338 return weights;
1339}
1340
1341/* ----------------------------------------------------------------------------
1342 * Neighborhood Blending Pixel Shader (Third Pass) */
1343
1345 float4 offset,
1346 SMAATexture2D(colorTex),
1347 SMAATexture2D(blendTex),
1349 SMAATexture2D(velocityTex),
1350#endif
1351 int2 size)
1352{
1353 /* Fetch the blending weights for current pixel: */
1354 float4 a;
1355 a.x = SMAASample(blendTex, offset.xy()).w; // Right
1356 a.y = SMAASample(blendTex, offset.zw()).y; // Top
1357 a.z = SMAASample(blendTex, texcoord).z; // Left
1358 a.w = SMAASample(blendTex, texcoord).x; // Bottom
1359
1360 /* Is there any blending weight with a value greater than 0.0? */
1362 if (math::dot(a, float4(1.0f, 1.0f, 1.0f, 1.0f)) < 1e-5f) {
1363 float4 color = SMAASampleLevelZero(colorTex, texcoord);
1364
1365#if SMAA_REPROJECTION
1366 float2 velocity = SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, texcoord));
1367
1368 /* Pack velocity into the alpha channel: */
1369 color.a = math::sqrt(5.0f * math::length(velocity));
1370#endif
1371
1372 return color;
1373 }
1374 else {
1375 bool h = math::max(a.x, a.z) > math::max(a.y, a.w); /* `max(horizontal) > max(vertical)`. */
1376
1377 /* Calculate the blending offsets: */
1378 float4 blendingOffset = float4(0.0f, a.y, 0.0f, a.w);
1379 float2 blendingWeight = float2(a.y, a.w);
1380 SMAAMovc(float4(h), blendingOffset, float4(a.x, 0.0f, a.z, 0.0f));
1381 SMAAMovc(float2(h), blendingWeight, float2(a.x, a.z));
1382 blendingWeight /= math::dot(blendingWeight, float2(1.0f, 1.0f));
1383
1384 /* Calculate the texture coordinates: */
1385 float4 blendingCoord = float4(texcoord, texcoord) + blendingOffset / float4(size, -size);
1386
1387 /* We exploit bilinear filtering to mix current pixel with the chosen neighbor: */
1388 float4 color = blendingWeight.x * SMAASampleLevelZero(colorTex, blendingCoord.xy());
1389 color += blendingWeight.y * SMAASampleLevelZero(colorTex, blendingCoord.zw());
1390
1391#if SMAA_REPROJECTION
1392 /* Anti-alias velocity for proper reprojection in a later stage: */
1393 float2 velocity = blendingWeight.x *
1394 SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.xy()));
1395 velocity += blendingWeight.y *
1396 SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.zw()));
1397
1398 /* Pack velocity into the alpha channel: */
1399 color.a = math::sqrt(5.0f * math::length(velocity));
1400#endif
1401
1402 return color;
1403 }
1404}
1405
1412
1413void SMAAOperation::get_area_of_interest(const int /*input_idx*/,
1414 const rcti &output_area,
1415 rcti &r_input_area)
1416{
1417 r_input_area.xmax = output_area.xmax +
1419 r_input_area.xmin = output_area.xmin - math::max(math::max(SMAA_MAX_SEARCH_STEPS - 1, 1),
1421 r_input_area.ymax = output_area.ymax +
1423 r_input_area.ymin = output_area.ymin - math::max(math::max(SMAA_MAX_SEARCH_STEPS - 1, 1),
1425}
1426
1428 const rcti & /*area*/,
1429 Span<MemoryBuffer *> inputs)
1430{
1431 const MemoryBuffer *image = inputs[0];
1432 if (image->is_a_single_elem()) {
1433 copy_v4_v4(output->get_elem(0, 0), image->get_elem(0, 0));
1434 return;
1435 }
1436
1437 const int2 size = int2(image->get_width(), image->get_height());
1438 MemoryBuffer edges(DataType::Float2, size.x, size.y);
1439
1440 float3 luminance_coefficients;
1441 IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
1442
1443 threading::parallel_for(IndexRange(size.y), 1, [&](const IndexRange sub_y_range) {
1444 for (const int64_t y : sub_y_range) {
1445 for (const int64_t x : IndexRange(size.x)) {
1446 int2 texel = int2(x, y);
1447 float2 coordinates = (float2(texel) + float2(0.5f)) / float2(size);
1448
1449 float4 offset[3];
1450 SMAAEdgeDetectionVS(coordinates, size, offset);
1451
1452 float2 edge = SMAALumaEdgeDetectionPS(coordinates,
1453 offset,
1454 image,
1455 threshold_,
1456 luminance_coefficients,
1457 local_contrast_adaptation_factor_);
1458 copy_v2_v2(edges.get_elem(texel.x, texel.y), edge);
1459 }
1460 }
1461 });
1462
1463 MemoryBuffer blending_weights(DataType::Color, size.x, size.y);
1464
1466 area_texture.copy_from(areaTexBytes, area_texture.get_rect());
1467
1469 search_texture.copy_from(searchTexBytes, search_texture.get_rect());
1470
1471 threading::parallel_for(IndexRange(size.y), 1, [&](const IndexRange sub_y_range) {
1472 for (const int64_t y : sub_y_range) {
1473 for (const int64_t x : IndexRange(size.x)) {
1474 int2 texel = int2(x, y);
1475 float2 coordinates = (float2(texel) + float2(0.5f)) / float2(size);
1476
1477 float4 offset[3];
1478 float2 pixel_coordinates;
1479 SMAABlendingWeightCalculationVS(coordinates, size, pixel_coordinates, offset);
1480
1481 float4 weights = SMAABlendingWeightCalculationPS(coordinates,
1482 pixel_coordinates,
1483 offset,
1484 &edges,
1485 &area_texture,
1486 &search_texture,
1487 float4(0.0f),
1488 size,
1489 corner_rounding_);
1490 copy_v4_v4(blending_weights.get_elem(texel.x, texel.y), weights);
1491 }
1492 }
1493 });
1494
1495 threading::parallel_for(IndexRange(size.y), 1, [&](const IndexRange sub_y_range) {
1496 for (const int64_t y : sub_y_range) {
1497 for (const int64_t x : IndexRange(size.x)) {
1498 int2 texel = int2(x, y);
1499 float2 coordinates = (float2(texel) + float2(0.5f)) / float2(size);
1500
1501 float4 offset;
1502 SMAANeighborhoodBlendingVS(coordinates, size, offset);
1503
1504 float4 result = SMAANeighborhoodBlendingPS(
1505 coordinates, offset, image, &blending_weights, size);
1506 copy_v4_v4(output->get_elem(texel.x, texel.y), result);
1507 }
1508 }
1509 });
1510}
1511
1512} // namespace blender::compositor
MINLINE void copy_v4_v4(float r[4], const float a[4])
#define SEARCHTEX_HEIGHT
const unsigned char searchTexBytes[]
#define SEARCHTEX_WIDTH
#define AREATEX_HEIGHT
const unsigned char areaTexBytes[]
#define AREATEX_WIDTH
#define SMAATexturePass2D(tex)
#define SMAA_BRANCH
#define SMAASampleLevelZero(tex, coord)
#define SMAA_AREATEX_MAX_DISTANCE
#define SMAATexture2D(tex)
#define SMAA_AREATEX_MAX_DISTANCE_DIAG
#define SMAASamplePoint(tex, coord)
#define SMAASamplePointOffset(tex, coord, offset, size)
#define SMAA_DECODE_VELOCITY(sample)
#define SMAA_SEARCHTEX_PACKED_SIZE
#define SMAASample(tex, coord)
#define SMAA_SEARCHTEX_SELECT(sample)
#define SMAA_REPROJECTION
#define SMAASampleLevelZeroOffset(tex, coord, offset, size)
#define SMAA_MAX_SEARCH_STEPS
#define SMAA_AREATEX_PIXEL_SIZE
#define SMAA_AREATEX_SELECT(sample)
#define SMAA_MAX_SEARCH_STEPS_DIAG
#define mad(a, b, c)
#define SMAA_SEARCHTEX_SIZE
#define SMAA_PREDICATION
#define SMAA_AREATEX_SUBTEX_SIZE
#define saturate(a)
BLI_INLINE void IMB_colormanagement_get_luminance_coefficients(float r_rgb[3])
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
a MemoryBuffer contains access to the data
void add_output_socket(DataType datatype)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void update_memory_buffer(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override
Get input operation area being read by this operation on rendering given output area.
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
velocity_obj_prev_buf[] vec4
@ Float2
Float2 data type.
#define L
static float SMAASearchYUp(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
static void SMAANeighborhoodBlendingVS(float2 texcoord, int2 size, float4 &offset)
static float2 SMAASearchDiag2(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, int2 size, float2 &e)
static float2 SMAAAreaDiag(SMAATexture2D(areaTex), float2 dist, float2 e, float offset)
static void SMAADetectHorizontalCornerPattern(SMAATexture2D(edgesTex), float2 &weights, float4 texcoord, float2 d, int2 size, int corner_rounding)
static float2 SMAAArea(SMAATexture2D(areaTex), float2 dist, float e1, float e2, float offset)
static void SMAABlendingWeightCalculationVS(float2 texcoord, int2 size, float2 &pixcoord, float4 offset[3])
static float SMAASearchXRight(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
static float4 SMAABlendingWeightCalculationPS(float2 texcoord, float2 pixcoord, float4 offset[3], MemoryBuffer *edgesTex, MemoryBuffer *areaTex, MemoryBuffer *searchTex, float4 subsampleIndices, int2 size, int corner_rounding)
static float2 SMAASearchDiag1(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, int2 size, float2 &e)
static float2 SMAADecodeDiagBilinearAccess(float2 e)
static float SMAASearchYDown(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
static void SMAAMovc(float2 cond, float2 &variable, float2 value)
static float SMAASearchLength(SMAATexture2D(searchTex), float2 e, float offset)
static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex), SMAATexture2D(areaTex), float2 texcoord, float2 e, float4 subsampleIndices, int2 size)
static float4 SMAANeighborhoodBlendingPS(float2 texcoord, float4 offset, SMAATexture2D(colorTex), SMAATexture2D(blendTex), int2 size)
static void SMAAEdgeDetectionVS(float2 texcoord, int2 size, float4 offset[3])
static float SMAASearchXLeft(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
static float2 SMAALumaEdgeDetectionPS(float2 texcoord, float4 offset[3], SMAATexture2D(colorTex), float edge_threshold, float3 luminance_coefficients, float local_contrast_adaptation_factor)
static void SMAADetectVerticalCornerPattern(SMAATexture2D(edgesTex), float2 &weights, float4 texcoord, float2 d, int2 size, int corner_rounding)
T sqrt(const T &a)
T length(const VecBase< T, Size > &a)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T step(const T &edge, const T &value)
T interpolate(const T &a, const T &b, const FactorT &t)
T max(const T &a, const T &b)
T abs(const T &a)
T round(const T &a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
vec3(0.0)") .vertex_in(0
VecBase< T, 2 > zw() const
VecBase< T, 2 > xy() const
VecBase< T, 3 > xyz() const
int ymin
int ymax
int xmin
int xmax
int xy[2]
Definition wm_draw.cc:170