Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
109
libs/shaders/Metal/arrow3d.metal
Normal file
109
libs/shaders/Metal/arrow3d.metal
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_transform;
|
||||
float4x4 u_normalTransform;
|
||||
float4 u_color;
|
||||
float2 u_texCoordFlipping;
|
||||
} Uniforms_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float3 a_normal [[attribute(1)]];
|
||||
} Vertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float3 normal;
|
||||
} Fragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_texCoords [[attribute(1)]];
|
||||
} VertexShadow_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float intensity;
|
||||
} FragmentShadow_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float3 a_normal [[attribute(1)]];
|
||||
float2 a_texCoords [[attribute(2)]];
|
||||
} VertexTextured_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float3 normal;
|
||||
float2 texCoords;
|
||||
} FragmentTextured_T;
|
||||
|
||||
vertex Fragment_T vsArrow3d(const Vertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]])
|
||||
{
|
||||
Fragment_T out;
|
||||
out.position = uniforms.u_transform * float4(in.a_position, 1.0);
|
||||
out.normal = normalize((uniforms.u_normalTransform * float4(in.a_normal, 0.0)).xyz);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsArrow3d(const Fragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
constexpr float3 kLightDir = float3(0.316, 0.0, 0.948);
|
||||
float phongDiffuse = max(0.0, -dot(kLightDir, in.normal));
|
||||
return float4((phongDiffuse * 0.5 + 0.5) * uniforms.u_color.rgb, uniforms.u_color.a);
|
||||
}
|
||||
|
||||
vertex FragmentShadow_T vsArrow3dShadow(const VertexShadow_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]])
|
||||
{
|
||||
FragmentShadow_T out;
|
||||
out.position = uniforms.u_transform * float4(in.a_position, 1.0);
|
||||
out.intensity = in.a_texCoords.x;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsArrow3dShadow(const FragmentShadow_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
return float4(uniforms.u_color.rgb, uniforms.u_color.a * in.intensity);
|
||||
}
|
||||
|
||||
fragment float4 fsArrow3dOutline(const FragmentShadow_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
float alpha = smoothstep(0.7, 1.0, in.intensity);
|
||||
return float4(uniforms.u_color.rgb, uniforms.u_color.a * alpha);
|
||||
}
|
||||
|
||||
vertex FragmentTextured_T vsArrow3dTextured(const VertexTextured_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(3)]])
|
||||
{
|
||||
FragmentTextured_T out;
|
||||
out.position = uniforms.u_transform * float4(in.a_position, 1.0);
|
||||
out.normal = normalize((uniforms.u_normalTransform * float4(in.a_normal, 0.0)).xyz);
|
||||
out.texCoords = mix(in.a_texCoords, 1.0 - in.a_texCoords, uniforms.u_texCoordFlipping);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsArrow3dTextured(const FragmentTextured_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
constexpr float3 kLightDir = float3(0.316, 0.0, 0.948);
|
||||
float phongDiffuse = max(0.0, -dot(kLightDir, in.normal));
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.texCoords) * uniforms.u_color;
|
||||
return float4((phongDiffuse * 0.5 + 0.5) * color.rgb, color.a);
|
||||
}
|
||||
31
libs/shaders/Metal/debug_rect.metal
Normal file
31
libs/shaders/Metal/debug_rect.metal
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_position [[attribute(0)]];
|
||||
} Vertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
} Fragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 u_color;
|
||||
} Uniforms_T;
|
||||
|
||||
vertex Fragment_T vsDebugRect(const Vertex_T in [[stage_in]])
|
||||
{
|
||||
Fragment_T out;
|
||||
out.position = float4(in.a_position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsDebugRect(const Fragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
return uniforms.u_color;
|
||||
}
|
||||
162
libs/shaders/Metal/gui.metal
Normal file
162
libs/shaders/Metal/gui.metal
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_modelView;
|
||||
float4x4 u_projection;
|
||||
packed_float2 u_contrastGamma;
|
||||
packed_float2 u_position;
|
||||
float u_isOutlinePass;
|
||||
float u_opacity;
|
||||
float u_length;
|
||||
} Uniforms_T;
|
||||
|
||||
// Ruler
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_position [[attribute(0)]];
|
||||
float2 a_normal [[attribute(1)]];
|
||||
float2 a_texCoords [[attribute(2)]];
|
||||
} RulerVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
half4 color;
|
||||
} RulerFragment_T;
|
||||
|
||||
vertex RulerFragment_T vsRuler(const RulerVertex_T in [[stage_in]],
|
||||
texture2d<half> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
RulerFragment_T out;
|
||||
float2 p = uniforms.u_position + in.a_position + uniforms.u_length * in.a_normal;
|
||||
out.position = float4(p, 0.0, 1.0) * uniforms.u_projection;
|
||||
half4 color = u_colorTex.sample(u_colorTexSampler, in.a_texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment half4 fsRuler(const RulerFragment_T in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
}
|
||||
|
||||
// TextStaticOutlinedGui / TextOutlinedGui
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_colorTexCoord [[attribute(1)]];
|
||||
float2 a_outlineColorTexCoord [[attribute(2)]];
|
||||
float2 a_normal [[attribute(3)]];
|
||||
float2 a_maskTexCoord [[attribute(4)]];
|
||||
} TextStaticOutlinedGuiVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_colorTexCoord [[attribute(1)]];
|
||||
float2 a_outlineColorTexCoord [[attribute(2)]];
|
||||
float2 a_normal [[attribute(3)]];
|
||||
float2 a_maskTexCoord [[attribute(4)]];
|
||||
} TextOutlinedGuiVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
half4 glyphColor;
|
||||
float2 maskTexCoord;
|
||||
} TextOutlinedGuiFragment_T;
|
||||
|
||||
TextOutlinedGuiFragment_T ComputeTextOutlinedGuiVertex(constant Uniforms_T & uniforms, float3 a_position, float2 a_normal,
|
||||
float2 a_colorTexCoord, float2 a_outlineColorTexCoord,
|
||||
float2 a_maskTexCoord, texture2d<half> u_colorTex,
|
||||
sampler u_colorTexSampler)
|
||||
{
|
||||
constexpr float kBaseDepthShift = -10.0;
|
||||
|
||||
TextOutlinedGuiFragment_T out;
|
||||
|
||||
float isOutline = step(0.5, uniforms.u_isOutlinePass);
|
||||
float depthShift = kBaseDepthShift * isOutline;
|
||||
|
||||
float4 pos = (float4(a_position, 1.0) + float4(0.0, 0.0, depthShift, 0.0)) * uniforms.u_modelView;
|
||||
float4 shiftedPos = float4(a_normal, 0.0, 0.0) + pos;
|
||||
out.position = shiftedPos * uniforms.u_projection;
|
||||
out.glyphColor = u_colorTex.sample(u_colorTexSampler,
|
||||
mix(a_colorTexCoord, a_outlineColorTexCoord, isOutline));
|
||||
out.maskTexCoord = a_maskTexCoord;
|
||||
return out;
|
||||
}
|
||||
|
||||
vertex TextOutlinedGuiFragment_T vsTextStaticOutlinedGui(const TextStaticOutlinedGuiVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<half> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
return ComputeTextOutlinedGuiVertex(uniforms, in.a_position, in.a_normal, in.a_colorTexCoord,
|
||||
in.a_outlineColorTexCoord, in.a_maskTexCoord,
|
||||
u_colorTex, u_colorTexSampler);
|
||||
}
|
||||
|
||||
vertex TextOutlinedGuiFragment_T vsTextOutlinedGui(const TextOutlinedGuiVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]],
|
||||
texture2d<half> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
return ComputeTextOutlinedGuiVertex(uniforms, in.a_position, in.a_normal, in.a_colorTexCoord,
|
||||
in.a_outlineColorTexCoord, in.a_maskTexCoord,
|
||||
u_colorTex, u_colorTexSampler);
|
||||
}
|
||||
|
||||
fragment half4 fsTextOutlinedGui(const TextOutlinedGuiFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_maskTex [[texture(0)]],
|
||||
sampler u_maskTexSampler [[sampler(0)]])
|
||||
{
|
||||
half4 glyphColor = in.glyphColor;
|
||||
float dist = u_maskTex.sample(u_maskTexSampler, in.maskTexCoord).a;
|
||||
float2 contrastGamma = uniforms.u_contrastGamma;
|
||||
float alpha = smoothstep(contrastGamma.x - contrastGamma.y, contrastGamma.x + contrastGamma.y, dist);
|
||||
glyphColor.a *= (alpha * uniforms.u_opacity);
|
||||
return glyphColor;
|
||||
}
|
||||
|
||||
// TexturingGui
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_position [[attribute(0)]];
|
||||
float2 a_texCoords [[attribute(1)]];
|
||||
} TexturingGuiVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 texCoords;
|
||||
} TexturingGuiFragment_T;
|
||||
|
||||
vertex TexturingGuiFragment_T vsTexturingGui(const TexturingGuiVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
TexturingGuiFragment_T out;
|
||||
out.position = float4(in.a_position, 0.0, 1.0) * uniforms.u_modelView * uniforms.u_projection;
|
||||
out.texCoords = in.a_texCoords;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsTexturingGui(const TexturingGuiFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
return color;
|
||||
}
|
||||
39
libs/shaders/Metal/imgui.metal
Normal file
39
libs/shaders/Metal/imgui.metal
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_position [[attribute(0)]];
|
||||
float2 a_texCoords [[attribute(1)]];
|
||||
float4 a_color [[attribute(2)]];
|
||||
} Vertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 texCoords;
|
||||
float4 color;
|
||||
} Fragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_projection;
|
||||
} Uniforms_T;
|
||||
|
||||
vertex Fragment_T vsImGui(const Vertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
Fragment_T out;
|
||||
out.position = float4(in.a_position, 0.0, 1.0) * uniforms.u_projection;
|
||||
out.texCoords = in.a_texCoords;
|
||||
out.color = in.a_color;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsImGui(const Fragment_T in [[stage_in]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
return in.color * u_colorTex.sample(u_colorTexSampler, in.texCoords);
|
||||
}
|
||||
841
libs/shaders/Metal/map.metal
Normal file
841
libs/shaders/Metal/map.metal
Normal file
|
|
@ -0,0 +1,841 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
#include "shaders_lib.h"
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_modelView;
|
||||
float4x4 u_projection;
|
||||
float4x4 u_pivotTransform;
|
||||
packed_float2 u_contrastGamma;
|
||||
float u_opacity;
|
||||
float u_zScale;
|
||||
float u_interpolation;
|
||||
float u_isOutlinePass;
|
||||
} Uniforms_T;
|
||||
|
||||
// Area/AreaOutline
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_texCoords [[attribute(1)]];
|
||||
} AreaVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
half4 color;
|
||||
} AreaFragment_T;
|
||||
|
||||
vertex AreaFragment_T vsArea(const AreaVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<half> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
AreaFragment_T out;
|
||||
float4 pos = float4(in.a_position, 1.0) * uniforms.u_modelView * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
half4 color = u_colorTex.sample(u_colorTexSampler, in.a_texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment half4 fsArea(const AreaFragment_T in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
}
|
||||
|
||||
// Area3d
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float3 a_normal [[attribute(1)]];
|
||||
float2 a_texCoords [[attribute(2)]];
|
||||
} Area3dVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
half4 color;
|
||||
float intensity;
|
||||
} Area3dFragment_T;
|
||||
|
||||
vertex Area3dFragment_T vsArea3d(const Area3dVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<half> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
constexpr float4 kNormalizedLightDir = float4(0.3162, 0.0, 0.9486, 0.0);
|
||||
|
||||
Area3dFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position, 1.0) * uniforms.u_modelView;
|
||||
|
||||
float4 normal = float4(in.a_position + in.a_normal, 1.0) * uniforms.u_modelView;
|
||||
normal.xyw = (normal * uniforms.u_projection).xyw;
|
||||
normal.z = normal.z * uniforms.u_zScale;
|
||||
|
||||
pos.xyw = (pos * uniforms.u_projection).xyw;
|
||||
pos.z = in.a_position.z * uniforms.u_zScale;
|
||||
|
||||
float4 normDir = normal - pos;
|
||||
if (dot(normDir, normDir) != 0.0)
|
||||
out.intensity = max(0.0, -dot(kNormalizedLightDir, normalize(normDir)));
|
||||
else
|
||||
out.intensity = 0.0;
|
||||
|
||||
out.position = uniforms.u_pivotTransform * pos;
|
||||
|
||||
half4 color = u_colorTex.sample(u_colorTexSampler, in.a_texCoords);
|
||||
color.a = (half)uniforms.u_opacity;
|
||||
out.color = color;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment half4 fsArea3d(const Area3dFragment_T in [[stage_in]])
|
||||
{
|
||||
return half4(in.color.rgb * (in.intensity * 0.2 + 0.8), in.color.a);
|
||||
}
|
||||
|
||||
// Area3dOutline
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_texCoords [[attribute(1)]];
|
||||
} Area3dOutlineVertex_T;
|
||||
|
||||
vertex AreaFragment_T vsArea3dOutline(const Area3dOutlineVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<half> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
AreaFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position, 1.0) * uniforms.u_modelView;
|
||||
pos.xyw = (pos * uniforms.u_projection).xyw;
|
||||
pos.z = in.a_position.z * uniforms.u_zScale;
|
||||
out.position = uniforms.u_pivotTransform * pos;
|
||||
|
||||
half4 color = u_colorTex.sample(u_colorTexSampler, in.a_texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
return out;
|
||||
}
|
||||
|
||||
// HatchingArea
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_colorTexCoords [[attribute(1)]];
|
||||
float2 a_maskTexCoords [[attribute(2)]];
|
||||
} HatchingAreaVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
half4 color;
|
||||
float2 maskTexCoords;
|
||||
} HatchingAreaFragment_T;
|
||||
|
||||
vertex HatchingAreaFragment_T vsHatchingArea(const HatchingAreaVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<half> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
HatchingAreaFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position, 1.0) * uniforms.u_modelView * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
out.maskTexCoords = in.a_maskTexCoords;
|
||||
half4 color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment half4 fsHatchingArea(const HatchingAreaFragment_T in [[stage_in]],
|
||||
texture2d<half> u_maskTex [[texture(0)]],
|
||||
sampler u_maskTexSampler [[sampler(0)]])
|
||||
{
|
||||
return in.color * u_maskTex.sample(u_maskTexSampler, in.maskTexCoords);
|
||||
}
|
||||
|
||||
// CirclePoint
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_normal [[attribute(0)]];
|
||||
float3 a_position [[attribute(1)]];
|
||||
float4 a_color [[attribute(2)]];
|
||||
} CirclePointVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float3 radius;
|
||||
float4 color;
|
||||
} CirclePointFragment_T;
|
||||
|
||||
vertex CirclePointFragment_T vsCirclePoint(const CirclePointVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]])
|
||||
{
|
||||
CirclePointFragment_T out;
|
||||
|
||||
float3 radius = in.a_normal * in.a_position.z;
|
||||
float4 pos = float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView;
|
||||
float4 shiftedPos = float4(radius.xy, 0.0, 0.0) + pos;
|
||||
out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.radius = radius;
|
||||
out.color = in.a_color;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsCirclePoint(const CirclePointFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
constexpr float kAntialiasingScalar = 0.9;
|
||||
|
||||
float d = dot(in.radius.xy, in.radius.xy);
|
||||
float4 color = in.color;
|
||||
float aaRadius = in.radius.z * kAntialiasingScalar;
|
||||
float stepValue = 1.0 - smoothstep(aaRadius * aaRadius, in.radius.z * in.radius.z, d);
|
||||
color.a *= (uniforms.u_opacity * stepValue);
|
||||
return color;
|
||||
}
|
||||
|
||||
// Line
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float3 a_normal [[attribute(1)]];
|
||||
float2 a_texCoords [[attribute(2)]];
|
||||
} LineVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
//float2 halfLength;
|
||||
} LineFragment_T;
|
||||
|
||||
vertex LineFragment_T vsLine(const LineVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
LineFragment_T out;
|
||||
|
||||
float2 normal = in.a_normal.xy;
|
||||
float halfWidth = length(normal);
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
if (halfWidth != 0.0)
|
||||
{
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + normal,
|
||||
uniforms.u_modelView, halfWidth);
|
||||
}
|
||||
|
||||
//out.halfLength = float2(sign(in.a_normal.z) * halfWidth, abs(in.a_normal.z));
|
||||
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.a_texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsLine(const LineFragment_T in [[stage_in]])
|
||||
{
|
||||
// Disabled too agressive AA-like blurring of edges,
|
||||
// see https://github.com/organicmaps/organicmaps/issues/6583.
|
||||
//constexpr float kAntialiasingPixelsCount = 2.5;
|
||||
|
||||
//float currentW = abs(in.halfLength.x);
|
||||
//float diff = in.halfLength.y - currentW;
|
||||
|
||||
float4 color = in.color;
|
||||
//color.a *= mix(0.3, 1.0, saturate(diff / kAntialiasingPixelsCount));
|
||||
return color;
|
||||
}
|
||||
|
||||
// DashedLine
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float3 a_normal [[attribute(1)]];
|
||||
float2 a_colorTexCoord [[attribute(2)]];
|
||||
float4 a_maskTexCoord [[attribute(3)]];
|
||||
} DashedLineVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
float2 maskTexCoord;
|
||||
//float2 halfLength;
|
||||
} DashedLineFragment_T;
|
||||
|
||||
vertex DashedLineFragment_T vsDashedLine(const DashedLineVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
DashedLineFragment_T out;
|
||||
|
||||
float2 normal = in.a_normal.xy;
|
||||
float halfWidth = length(normal);
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
if (halfWidth != 0.0)
|
||||
{
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + normal,
|
||||
uniforms.u_modelView, halfWidth);
|
||||
}
|
||||
|
||||
float uOffset = min(length(float4(kShapeCoordScalar, 0.0, 0.0, 0.0) * uniforms.u_modelView) * in.a_maskTexCoord.x, 1.0);
|
||||
out.maskTexCoord = float2(in.a_maskTexCoord.y + uOffset * in.a_maskTexCoord.z, in.a_maskTexCoord.w);
|
||||
|
||||
//out.halfLength = float2(sign(in.a_normal.z) * halfWidth, abs(in.a_normal.z));
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsDashedLine(const DashedLineFragment_T in [[stage_in]],
|
||||
texture2d<float> u_maskTex [[texture(0)]],
|
||||
sampler u_maskTexSampler [[sampler(0)]])
|
||||
{
|
||||
// Disabled too agressive AA-like blurring of edges,
|
||||
// see https://github.com/organicmaps/organicmaps/issues/6583.
|
||||
//constexpr float kAntialiasingPixelsCount = 2.5;
|
||||
|
||||
float4 color = in.color;
|
||||
color.a *= u_maskTex.sample(u_maskTexSampler, in.maskTexCoord).a;
|
||||
|
||||
//float currentW = abs(in.halfLength.x);
|
||||
//float diff = in.halfLength.y - currentW;
|
||||
//color.a *= mix(0.3, 1.0, saturate(diff / kAntialiasingPixelsCount));
|
||||
return color;
|
||||
}
|
||||
|
||||
// CapJoin
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float3 a_normal [[attribute(1)]];
|
||||
float2 a_texCoords [[attribute(2)]];
|
||||
} CapJoinVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
float3 radius;
|
||||
} CapJoinFragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} CapJoinFragment_Output;
|
||||
|
||||
vertex CapJoinFragment_T vsCapJoin(const CapJoinVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
CapJoinFragment_T out;
|
||||
|
||||
float4 p = float4(in.a_position, 1.0) * uniforms.u_modelView;
|
||||
float4 pos = float4(in.a_normal.xy, 0.0, 0.0) + p;
|
||||
out.position = ApplyPivotTransform(pos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.radius = in.a_normal;
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.a_texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment CapJoinFragment_Output fsCapJoin(const CapJoinFragment_T in [[stage_in]])
|
||||
{
|
||||
constexpr float kAntialiasingPixelsCount = 2.5;
|
||||
|
||||
CapJoinFragment_Output out;
|
||||
|
||||
float smallRadius = in.radius.z - kAntialiasingPixelsCount;
|
||||
float stepValue = 1.0 - smoothstep(smallRadius * smallRadius, in.radius.z * in.radius.z,
|
||||
in.radius.x * in.radius.x + in.radius.y * in.radius.y);
|
||||
out.color = in.color;
|
||||
out.color.a *= stepValue;
|
||||
|
||||
if (out.color.a < 0.001)
|
||||
out.depth = 1.0;
|
||||
else
|
||||
out.depth = in.position.z;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// PathSymbol
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 a_position [[attribute(0)]];
|
||||
float2 a_normal [[attribute(1)]];
|
||||
float2 a_texCoords [[attribute(2)]];
|
||||
} PathSymbolVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 texCoords;
|
||||
} PathSymbolFragment_T;
|
||||
|
||||
vertex PathSymbolFragment_T vsPathSymbol(const PathSymbolVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
PathSymbolFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
|
||||
float normalLen = length(in.a_normal);
|
||||
float4 n = float4(in.a_position.xy + in.a_normal * kShapeCoordScalar, 0.0, 0.0) * uniforms.u_modelView;
|
||||
float4 norm;
|
||||
if (dot(n, n) != 0.0)
|
||||
norm = normalize(n) * normalLen;
|
||||
else
|
||||
norm = float4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
float4 shiftedPos = norm + pos;
|
||||
out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.texCoords = in.a_texCoords;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsPathSymbol(const PathSymbolFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
return color;
|
||||
}
|
||||
|
||||
// Text
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_colorTexCoord [[attribute(0)]];
|
||||
float2 a_maskTexCoord [[attribute(1)]];
|
||||
float4 a_position [[attribute(2)]];
|
||||
float2 a_normal [[attribute(3)]];
|
||||
} TextVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
float2 maskTexCoord;
|
||||
} TextFragment_T;
|
||||
|
||||
vertex TextFragment_T vsText(const TextVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
TextFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 shiftedPos = float4(in.a_normal, 0.0, 0.0) + pos;
|
||||
out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.maskTexCoord = in.a_maskTexCoord;
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsText(const TextFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_maskTex [[texture(0)]],
|
||||
sampler u_maskTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 glyphColor = in.color;
|
||||
float dist = u_maskTex.sample(u_maskTexSampler, in.maskTexCoord).a;
|
||||
float2 contrastGamma = uniforms.u_contrastGamma;
|
||||
float alpha = smoothstep(contrastGamma.x - contrastGamma.y, contrastGamma.x + contrastGamma.y, dist);
|
||||
glyphColor.a *= alpha * uniforms.u_opacity;
|
||||
return glyphColor;
|
||||
}
|
||||
|
||||
// TextBillboard
|
||||
|
||||
vertex TextFragment_T vsTextBillboard(const TextVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
TextFragment_T out;
|
||||
|
||||
float4 pivot = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 offset = float4(in.a_normal, 0.0, 0.0) * uniforms.u_projection;
|
||||
out.position = ApplyBillboardPivotTransform(pivot * uniforms.u_projection, uniforms.u_pivotTransform,
|
||||
in.a_position.w * uniforms.u_zScale, offset.xy);
|
||||
out.maskTexCoord = in.a_maskTexCoord;
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord);
|
||||
return out;
|
||||
}
|
||||
|
||||
// TextOutlined
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_colorTexCoord [[attribute(0)]];
|
||||
float2 a_outlineColorTexCoord [[attribute(1)]];
|
||||
float2 a_maskTexCoord [[attribute(2)]];
|
||||
float4 a_position [[attribute(3)]];
|
||||
float2 a_normal [[attribute(4)]];
|
||||
} TextOutlinedVertex_T;
|
||||
|
||||
vertex TextFragment_T vsTextOutlined(const TextOutlinedVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
constexpr float kBaseDepthShift = -10.0;
|
||||
|
||||
TextFragment_T out;
|
||||
|
||||
float isOutline = step(0.5, uniforms.u_isOutlinePass);
|
||||
float notOutline = 1.0 - isOutline;
|
||||
float depthShift = kBaseDepthShift * isOutline;
|
||||
|
||||
float4 pos = (float4(in.a_position.xyz, 1.0) + float4(0.0, 0.0, depthShift, 0.0)) * uniforms.u_modelView;
|
||||
float4 shiftedPos = float4(in.a_normal, 0.0, 0.0) + pos;
|
||||
out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.maskTexCoord = in.a_maskTexCoord;
|
||||
float2 colorTexCoord = in.a_colorTexCoord * notOutline + in.a_outlineColorTexCoord * isOutline;
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, colorTexCoord);
|
||||
return out;
|
||||
}
|
||||
|
||||
// TextOutlinedBillboard
|
||||
|
||||
vertex TextFragment_T vsTextOutlinedBillboard(const TextOutlinedVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(2)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
constexpr float kBaseDepthShift = -10.0;
|
||||
|
||||
TextFragment_T out;
|
||||
|
||||
float isOutline = step(0.5, uniforms.u_isOutlinePass);
|
||||
float depthShift = kBaseDepthShift * isOutline;
|
||||
|
||||
float4 pivot = (float4(in.a_position.xyz, 1.0) + float4(0.0, 0.0, depthShift, 0.0)) * uniforms.u_modelView;
|
||||
float4 offset = float4(in.a_normal, 0.0, 0.0) * uniforms.u_projection;
|
||||
out.position = ApplyBillboardPivotTransform(pivot * uniforms.u_projection, uniforms.u_pivotTransform,
|
||||
in.a_position.w * uniforms.u_zScale, offset.xy);
|
||||
out.maskTexCoord = in.a_maskTexCoord;
|
||||
float2 colorTexCoord = mix(in.a_colorTexCoord, in.a_outlineColorTexCoord, isOutline);
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, colorTexCoord);
|
||||
return out;
|
||||
}
|
||||
|
||||
// TextFixed
|
||||
/*
|
||||
fragment float4 fsTextFixed(const TextFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_maskTex [[texture(0)]],
|
||||
sampler u_maskTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 glyphColor = in.color;
|
||||
float alpha = u_maskTex.sample(u_maskTexSampler, in.maskTexCoord).a;
|
||||
glyphColor.a *= alpha * uniforms.u_opacity;
|
||||
return glyphColor;
|
||||
}
|
||||
*/
|
||||
// ColoredSymbol
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float4 a_normal [[attribute(1)]];
|
||||
float4 a_colorTexCoords [[attribute(2)]];
|
||||
} ColoredSymbolVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 normal;
|
||||
float4 color;
|
||||
} ColoredSymbolFragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} ColoredSymbolOut_T;
|
||||
|
||||
vertex ColoredSymbolFragment_T vsColoredSymbol(const ColoredSymbolVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
ColoredSymbolFragment_T out;
|
||||
|
||||
float4 p = float4(in.a_position, 1.0) * uniforms.u_modelView;
|
||||
float4 pos = float4(in.a_normal.xy + in.a_colorTexCoords.zw, 0.0, 0.0) + p;
|
||||
out.position = ApplyPivotTransform(pos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoords.xy);
|
||||
out.normal = in.a_normal;
|
||||
return out;
|
||||
}
|
||||
|
||||
vertex ColoredSymbolFragment_T vsColoredSymbolBillboard(const ColoredSymbolVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
ColoredSymbolFragment_T out;
|
||||
|
||||
float4 pivot = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 offset = float4(in.a_normal.xy + in.a_colorTexCoords.zw, 0.0, 0.0) * uniforms.u_projection;
|
||||
out.position = ApplyBillboardPivotTransform(pivot * uniforms.u_projection, uniforms.u_pivotTransform, 0.0, offset.xy);
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoords.xy);
|
||||
out.normal = in.a_normal;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment ColoredSymbolOut_T fsColoredSymbol(const ColoredSymbolFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
constexpr float kAntialiasingPixelsCount = 2.5;
|
||||
|
||||
ColoredSymbolOut_T out;
|
||||
|
||||
float r1 = (in.normal.z - kAntialiasingPixelsCount) * (in.normal.z - kAntialiasingPixelsCount);
|
||||
float r2 = in.normal.x * in.normal.x + in.normal.y * in.normal.y;
|
||||
float r3 = in.normal.z * in.normal.z;
|
||||
float alpha = mix(step(r3, r2), smoothstep(r1, r3, r2), in.normal.w);
|
||||
|
||||
float4 finalColor = in.color;
|
||||
finalColor.a = finalColor.a * uniforms.u_opacity * (1.0 - alpha);
|
||||
if (finalColor.a == 0.0)
|
||||
out.depth = 1.0;
|
||||
else
|
||||
out.depth = in.position.z;
|
||||
|
||||
out.color = finalColor;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Texturing
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 a_position [[attribute(0)]];
|
||||
float2 a_normal [[attribute(1)]];
|
||||
float2 a_colorTexCoords [[attribute(2)]];
|
||||
} TexturingVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 colorTexCoords;
|
||||
} TexturingFragment_T;
|
||||
|
||||
vertex TexturingFragment_T vsTexturing(const TexturingVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
TexturingFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 shiftedPos = float4(in.a_normal, 0.0, 0.0) + pos;
|
||||
out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.colorTexCoords = in.a_colorTexCoords;
|
||||
return out;
|
||||
}
|
||||
|
||||
vertex TexturingFragment_T vsTexturingBillboard(const TexturingVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
TexturingFragment_T out;
|
||||
|
||||
float4 pivot = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 offset = float4(in.a_normal, 0.0, 0.0) * uniforms.u_projection;
|
||||
out.position = ApplyBillboardPivotTransform(pivot * uniforms.u_projection, uniforms.u_pivotTransform,
|
||||
in.a_position.w * uniforms.u_zScale, offset.xy);
|
||||
out.colorTexCoords = in.a_colorTexCoords;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsTexturing(const TexturingFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 finalColor = u_colorTex.sample(u_colorTexSampler, in.colorTexCoords.xy);
|
||||
finalColor.a *= uniforms.u_opacity;
|
||||
return finalColor;
|
||||
}
|
||||
|
||||
// MaskedTexturing
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 a_position [[attribute(0)]];
|
||||
float2 a_normal [[attribute(1)]];
|
||||
float2 a_colorTexCoords [[attribute(2)]];
|
||||
float2 a_maskTexCoords [[attribute(3)]];
|
||||
} MaskedTexturingVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 colorTexCoords;
|
||||
float2 maskTexCoords;
|
||||
} MaskedTexturingFragment_T;
|
||||
|
||||
vertex MaskedTexturingFragment_T vsMaskedTexturing(const MaskedTexturingVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
MaskedTexturingFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 shiftedPos = float4(in.a_normal, 0.0, 0.0) + pos;
|
||||
out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.colorTexCoords = in.a_colorTexCoords;
|
||||
out.maskTexCoords = in.a_maskTexCoords;
|
||||
return out;
|
||||
}
|
||||
|
||||
vertex MaskedTexturingFragment_T vsMaskedTexturingBillboard(const MaskedTexturingVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
MaskedTexturingFragment_T out;
|
||||
|
||||
float4 pivot = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 offset = float4(in.a_normal, 0.0, 0.0) * uniforms.u_projection;
|
||||
out.position = ApplyBillboardPivotTransform(pivot * uniforms.u_projection, uniforms.u_pivotTransform,
|
||||
in.a_position.w * uniforms.u_zScale, offset.xy);
|
||||
out.colorTexCoords = in.a_colorTexCoords;
|
||||
out.maskTexCoords = in.a_maskTexCoords;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsMaskedTexturing(const MaskedTexturingFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]],
|
||||
texture2d<float> u_maskTex [[texture(1)]],
|
||||
sampler u_maskTexSampler [[sampler(1)]])
|
||||
{
|
||||
float4 finalColor = u_colorTex.sample(u_colorTexSampler, in.colorTexCoords.xy) *
|
||||
u_maskTex.sample(u_maskTexSampler, in.maskTexCoords.xy);
|
||||
finalColor.a *= uniforms.u_opacity;
|
||||
return finalColor;
|
||||
}
|
||||
|
||||
// UserMark
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float3 a_normalAndAnimateOrZ [[attribute(1)]];
|
||||
float4 a_texCoords [[attribute(2)]];
|
||||
float4 a_color [[attribute(3)]];
|
||||
} UserMarkVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 texCoords;
|
||||
float4 maskColor;
|
||||
} UserMarkFragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} UserMarkOut_T;
|
||||
|
||||
vertex UserMarkFragment_T vsUserMark(const UserMarkVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
UserMarkFragment_T out;
|
||||
|
||||
float2 normal = in.a_normalAndAnimateOrZ.xy;
|
||||
if (in.a_normalAndAnimateOrZ.z > 0.0)
|
||||
normal = uniforms.u_interpolation * normal;
|
||||
|
||||
float4 p = float4(in.a_position, 1.0) * uniforms.u_modelView;
|
||||
float4 pos = float4(normal, 0.0, 0.0) + p;
|
||||
float4 projectedPivot = p * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
float newZ = projectedPivot.y / projectedPivot.w * 0.5 + 0.5;
|
||||
out.position.z = abs(in.a_normalAndAnimateOrZ.z) * newZ + (1.0 - abs(in.a_normalAndAnimateOrZ.z)) * out.position.z;
|
||||
|
||||
out.texCoords = in.a_texCoords;
|
||||
out.maskColor = in.a_color;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
vertex UserMarkFragment_T vsUserMarkBillboard(const UserMarkVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
UserMarkFragment_T out;
|
||||
|
||||
float2 normal = in.a_normalAndAnimateOrZ.xy;
|
||||
if (in.a_normalAndAnimateOrZ.z > 0.0)
|
||||
normal = uniforms.u_interpolation * normal;
|
||||
|
||||
float4 pivot = float4(in.a_position.xyz, 1.0) * uniforms.u_modelView;
|
||||
float4 offset = float4(normal, 0.0, 0.0) * uniforms.u_projection;
|
||||
float4 projectedPivot = pivot * uniforms.u_projection;
|
||||
out.position = ApplyBillboardPivotTransform(projectedPivot, uniforms.u_pivotTransform, 0.0, offset.xy);
|
||||
float newZ = projectedPivot.y / projectedPivot.w * 0.5 + 0.5;
|
||||
out.position.z = abs(in.a_normalAndAnimateOrZ.z) * newZ + (1.0 - abs(in.a_normalAndAnimateOrZ.z)) * out.position.z;
|
||||
|
||||
out.texCoords = in.a_texCoords;
|
||||
out.maskColor = in.a_color;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment UserMarkOut_T fsUserMark(const UserMarkFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
UserMarkOut_T out;
|
||||
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.texCoords.xy);
|
||||
float4 bgColor = u_colorTex.sample(u_colorTexSampler, in.texCoords.zw) * float4(in.maskColor.xyz, 1.0);
|
||||
float4 finalColor = mix(color, mix(bgColor, color, color.a), bgColor.a);
|
||||
finalColor.a = clamp(color.a + bgColor.a, 0.0, 1.0) * uniforms.u_opacity * in.maskColor.w;
|
||||
if (finalColor.a < 0.001)
|
||||
out.depth = 1.0;
|
||||
else
|
||||
out.depth = in.position.z;
|
||||
out.color = finalColor;
|
||||
return out;
|
||||
}
|
||||
241
libs/shaders/Metal/route.metal
Normal file
241
libs/shaders/Metal/route.metal
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
#include "shaders_lib.h"
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_modelView;
|
||||
float4x4 u_projection;
|
||||
float4x4 u_pivotTransform;
|
||||
float4 u_routeParams;
|
||||
float4 u_color;
|
||||
float4 u_maskColor;
|
||||
float4 u_outlineColor;
|
||||
float4 u_fakeColor;
|
||||
float4 u_fakeOutlineColor;
|
||||
packed_float2 u_fakeBorders;
|
||||
packed_float2 u_pattern;
|
||||
packed_float2 u_angleCosSin;
|
||||
float u_arrowHalfWidth;
|
||||
float u_opacity;
|
||||
} Uniforms_T;
|
||||
|
||||
// Route/RouteDash
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_normal [[attribute(1)]];
|
||||
float3 a_length [[attribute(2)]];
|
||||
float4 a_color [[attribute(3)]];
|
||||
} RouteVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float3 lengthParams;
|
||||
float4 color;
|
||||
} RouteFragment_T;
|
||||
|
||||
vertex RouteFragment_T vsRoute(const RouteVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
RouteFragment_T out;
|
||||
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
float2 len = float2(in.a_length.x, in.a_length.z);
|
||||
if (dot(in.a_normal, in.a_normal) != 0.0)
|
||||
{
|
||||
float2 norm = in.a_normal * uniforms.u_routeParams.x;
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm,
|
||||
uniforms.u_modelView, length(norm));
|
||||
if (uniforms.u_routeParams.y != 0.0)
|
||||
len = float2(in.a_length.x + in.a_length.y * uniforms.u_routeParams.y, in.a_length.z);
|
||||
}
|
||||
|
||||
out.lengthParams = float3(len, uniforms.u_routeParams.z);
|
||||
out.color = in.a_color;
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsRoute(const RouteFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
if (in.lengthParams.x < in.lengthParams.z)
|
||||
discard_fragment();
|
||||
|
||||
constexpr float kAntialiasingThreshold = 0.92;
|
||||
constexpr float kOutlineThreshold1 = 0.81;
|
||||
constexpr float kOutlineThreshold2 = 0.71;
|
||||
|
||||
float2 fb = uniforms.u_fakeBorders;
|
||||
float2 coefs = step(in.lengthParams.xx, fb);
|
||||
coefs.y = 1.0 - coefs.y;
|
||||
float4 mainColor = mix(uniforms.u_color, uniforms.u_fakeColor, coefs.x);
|
||||
mainColor = mix(mainColor, uniforms.u_fakeColor, coefs.y);
|
||||
float4 mainOutlineColor = mix(uniforms.u_outlineColor, uniforms.u_fakeOutlineColor, coefs.x);
|
||||
mainOutlineColor = mix(mainOutlineColor, uniforms.u_fakeOutlineColor, coefs.y);
|
||||
|
||||
float4 color = mix(mix(mainColor, float4(in.color.rgb, 1.0), in.color.a), mainColor,
|
||||
step(uniforms.u_routeParams.w, 0.0));
|
||||
color = mix(color, mainOutlineColor, step(kOutlineThreshold1, abs(in.lengthParams.y)));
|
||||
color = mix(color, mainOutlineColor,
|
||||
smoothstep(kOutlineThreshold2, kOutlineThreshold1, abs(in.lengthParams.y)));
|
||||
color.a *= (1.0 - smoothstep(kAntialiasingThreshold, 1.0, abs(in.lengthParams.y)));
|
||||
color = float4(mix(color.rgb, uniforms.u_maskColor.rgb, uniforms.u_maskColor.a), color.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
float AlphaFromPattern(float curLen, float2 dashGapLen)
|
||||
{
|
||||
float len = dashGapLen.x + dashGapLen.y;
|
||||
float offset = fract(curLen / len) * len;
|
||||
return step(offset, dashGapLen.x);
|
||||
}
|
||||
|
||||
fragment float4 fsRouteDash(const RouteFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
if (in.lengthParams.x < in.lengthParams.z)
|
||||
discard_fragment();
|
||||
|
||||
constexpr float kAntialiasingThreshold = 0.92;
|
||||
|
||||
float2 fb = uniforms.u_fakeBorders;
|
||||
float2 coefs = step(in.lengthParams.xx, fb);
|
||||
coefs.y = 1.0 - coefs.y;
|
||||
float4 mainColor = mix(uniforms.u_color, uniforms.u_fakeColor, coefs.x);
|
||||
mainColor = mix(mainColor, uniforms.u_fakeColor, coefs.y);
|
||||
|
||||
float4 color = mainColor + in.color;
|
||||
float a = 1.0 - smoothstep(kAntialiasingThreshold, 1.0, abs(in.lengthParams.y));
|
||||
color.a *= (a * AlphaFromPattern(in.lengthParams.x, uniforms.u_pattern));
|
||||
color = float4(mix(color.rgb, uniforms.u_maskColor.rgb, uniforms.u_maskColor.a), color.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
// RouteArrow
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 a_position [[attribute(0)]];
|
||||
float2 a_normal [[attribute(1)]];
|
||||
float2 a_texCoords [[attribute(2)]];
|
||||
} RouteArrowVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 texCoords;
|
||||
} RouteArrowFragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} RouteArrowFragment_Output;
|
||||
|
||||
vertex RouteArrowFragment_T vsRouteArrow(const RouteArrowVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
RouteArrowFragment_T out;
|
||||
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
if (dot(in.a_normal, in.a_normal) != 0.0)
|
||||
{
|
||||
float2 norm = in.a_normal * uniforms.u_arrowHalfWidth;
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm,
|
||||
uniforms.u_modelView, length(norm));
|
||||
}
|
||||
|
||||
out.texCoords = in.a_texCoords;
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment RouteArrowFragment_Output fsRouteArrow(const RouteArrowFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
RouteArrowFragment_Output output;
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
output.depth = in.position.z;
|
||||
if (color.a < 0.001)
|
||||
output.depth = 1.0;
|
||||
output.color = float4(mix(color.rgb, uniforms.u_maskColor.rgb, uniforms.u_maskColor.a), color.a);
|
||||
return output;
|
||||
}
|
||||
|
||||
// RouteMarker
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 a_position [[attribute(0)]];
|
||||
float3 a_normal [[attribute(1)]];
|
||||
float4 a_color [[attribute(2)]];
|
||||
} RouteMarkerVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 radius;
|
||||
float4 color;
|
||||
} RouteMarkerFragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} RouteMarkerFragment_Output;
|
||||
|
||||
vertex RouteMarkerFragment_T vsRouteMarker(const RouteMarkerVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
RouteMarkerFragment_T out;
|
||||
|
||||
float r = uniforms.u_routeParams.x * in.a_normal.z;
|
||||
float2 cs = uniforms.u_angleCosSin;
|
||||
float2 normal = float2(in.a_normal.x * cs.x - in.a_normal.y * cs.y,
|
||||
in.a_normal.x * cs.y + in.a_normal.y * cs.x);
|
||||
float4 radius = float4(normal * r, r, in.a_position.w);
|
||||
float4 pos = float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView;
|
||||
float2 shiftedPos = radius.xy + pos.xy;
|
||||
pos = float4(shiftedPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.radius = radius;
|
||||
out.color = in.a_color;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment RouteMarkerFragment_Output fsRouteMarker(const RouteMarkerFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
if (uniforms.u_routeParams.y > in.radius.w)
|
||||
discard_fragment();
|
||||
|
||||
RouteMarkerFragment_Output output;
|
||||
|
||||
constexpr float kAntialiasingPixelsCount = 2.5;
|
||||
float4 color = in.color;
|
||||
|
||||
float aaRadius = max(in.radius.z - kAntialiasingPixelsCount, 0.0);
|
||||
float stepValue = smoothstep(aaRadius * aaRadius, in.radius.z * in.radius.z,
|
||||
dot(in.radius.xy, in.radius.xy));
|
||||
color.a = color.a * uniforms.u_opacity * (1.0 - stepValue);
|
||||
|
||||
output.depth = in.position.z;
|
||||
if (color.a < 0.001)
|
||||
output.depth = 1.0;
|
||||
output.color = float4(mix(color.rgb, uniforms.u_maskColor.rgb, uniforms.u_maskColor.a), color.a);
|
||||
|
||||
return output;
|
||||
}
|
||||
40
libs/shaders/Metal/screen_quad.metal
Normal file
40
libs/shaders/Metal/screen_quad.metal
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_position [[attribute(0)]];
|
||||
float2 a_texCoords [[attribute(1)]];
|
||||
} Vertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 texCoords;
|
||||
} Fragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u_opacity;
|
||||
float u_invertV;
|
||||
} Uniforms_T;
|
||||
|
||||
vertex Fragment_T vsScreenQuad(const Vertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
Fragment_T out;
|
||||
out.position = float4(in.a_position, 0.0, 1.0);
|
||||
out.texCoords = mix(in.a_texCoords, float2(in.a_texCoords.x, 1.0 - in.a_texCoords.y), uniforms.u_invertV);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsScreenQuad(const Fragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.texCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
return color;
|
||||
}
|
||||
17
libs/shaders/Metal/shaders_lib.h
Normal file
17
libs/shaders/Metal/shaders_lib.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
// Scale factor in shape's coordinates transformation from tile's coordinate
|
||||
// system.
|
||||
constant float kShapeCoordScalar = 1000.0;
|
||||
|
||||
// This function applies a 2D->3D transformation matrix.
|
||||
float4 ApplyPivotTransform(float4 pivot, float4x4 pivotTransform, float pivotRealZ);
|
||||
|
||||
// This function applies a 2D->3D transformation matrix to billboards.
|
||||
float4 ApplyBillboardPivotTransform(float4 pivot, float4x4 pivotTransform, float pivotRealZ, float2 offset);
|
||||
|
||||
// This function calculates transformed position on an axis for line shaders family.
|
||||
float2 CalcLineTransformedAxisPos(float2 originalAxisPos, float2 shiftedPos, float4x4 modelView, float halfWidth);
|
||||
31
libs/shaders/Metal/shaders_lib.metal
Normal file
31
libs/shaders/Metal/shaders_lib.metal
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
float4 ApplyPivotTransform(float4 pivot, float4x4 pivotTransform, float pivotRealZ)
|
||||
{
|
||||
float4 transformedPivot = pivot;
|
||||
float w = transformedPivot.w;
|
||||
transformedPivot.xyw = (pivotTransform * float4(transformedPivot.xy, pivotRealZ, w)).xyw;
|
||||
transformedPivot.z *= transformedPivot.w / w;
|
||||
return transformedPivot;
|
||||
}
|
||||
|
||||
float2 CalcLineTransformedAxisPos(float2 originalAxisPos, float2 shiftedPos, float4x4 modelView, float halfWidth)
|
||||
{
|
||||
float2 p = (float4(shiftedPos, 0.0, 1.0) * modelView).xy;
|
||||
float2 d = p - originalAxisPos;
|
||||
if (dot(d, d) != 0.0)
|
||||
return originalAxisPos + normalize(d) * halfWidth;
|
||||
else
|
||||
return originalAxisPos;
|
||||
}
|
||||
|
||||
float4 ApplyBillboardPivotTransform(float4 pivot, float4x4 pivotTransform, float pivotRealZ, float2 offset)
|
||||
{
|
||||
float logicZ = pivot.z / pivot.w;
|
||||
float4 transformedPivot = pivotTransform * float4(pivot.xy, pivotRealZ, pivot.w);
|
||||
float4 scale = pivotTransform * float4(1.0, -1.0, 0.0, 1.0);
|
||||
return float4(transformedPivot.xy / transformedPivot.w, logicZ, 1.0) + float4(offset / scale.w * scale.x, 0.0, 0.0);
|
||||
}
|
||||
154
libs/shaders/Metal/shapes.metal
Normal file
154
libs/shaders/Metal/shapes.metal
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
#include "shaders_lib.h"
|
||||
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_modelView;
|
||||
float4x4 u_projection;
|
||||
float4x4 u_pivotTransform;
|
||||
packed_float3 u_position;
|
||||
float u_dummy1;
|
||||
packed_float2 u_lineParams;
|
||||
float u_accuracy;
|
||||
float u_zScale;
|
||||
float u_opacity;
|
||||
float u_azimut;
|
||||
} Uniforms_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_normal [[attribute(0)]];
|
||||
float2 a_colorTexCoords [[attribute(1)]];
|
||||
} Vertex_T;
|
||||
|
||||
// Accuracy
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 colorTexCoords;
|
||||
} FragmentAccuracy_T;
|
||||
|
||||
vertex FragmentAccuracy_T vsAccuracy(const Vertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
float3 uPosition = uniforms.u_position;
|
||||
float4 position = float4(uPosition.xy, 0.0, 1.0) * uniforms.u_modelView;
|
||||
float4 normal = float4(in.a_normal * uniforms.u_accuracy, 0.0, 0.0);
|
||||
position = (position + normal) * uniforms.u_projection;
|
||||
|
||||
FragmentAccuracy_T out;
|
||||
out.position = ApplyPivotTransform(position, uniforms.u_pivotTransform, uPosition.z * uniforms.u_zScale);
|
||||
out.colorTexCoords = in.a_colorTexCoords;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsAccuracy(const FragmentAccuracy_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.colorTexCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
return color;
|
||||
}
|
||||
|
||||
// MyPosition
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 colorTexCoords;
|
||||
} FragmentMyPosition_T;
|
||||
|
||||
vertex FragmentMyPosition_T vsMyPosition(const Vertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
float cosV;
|
||||
float sinV = sincos(uniforms.u_azimut, cosV);
|
||||
|
||||
float4x4 rotation;
|
||||
rotation[0] = float4(cosV, sinV, 0.0, 0.0);
|
||||
rotation[1] = float4(-sinV, cosV, 0.0, 0.0);
|
||||
rotation[2] = float4(0.0, 0.0, 1.0, 0.0);
|
||||
rotation[3] = float4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
float4 pos = float4(uniforms.u_position, 1.0) * uniforms.u_modelView;
|
||||
float4 normal = float4(in.a_normal, 0.0, 0.0);
|
||||
float4 shiftedPos = normal * rotation + pos;
|
||||
|
||||
FragmentMyPosition_T out;
|
||||
out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0);
|
||||
out.colorTexCoords = in.a_colorTexCoords;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsMyPosition(const FragmentMyPosition_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.colorTexCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
return color;
|
||||
}
|
||||
|
||||
// SelectionLine
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_normal [[attribute(1)]];
|
||||
float2 a_colorTexCoords [[attribute(2)]];
|
||||
float3 a_length [[attribute(3)]];
|
||||
} SelectionLineVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
float lengthY;
|
||||
} SelectionLineFragment_T;
|
||||
|
||||
vertex SelectionLineFragment_T vsSelectionLine(const SelectionLineVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
SelectionLineFragment_T out;
|
||||
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
float2 len = float2(in.a_length.x, in.a_length.z);
|
||||
float2 lineParams = uniforms.u_lineParams;
|
||||
if (dot(in.a_normal, in.a_normal) != 0.0)
|
||||
{
|
||||
float2 norm = in.a_normal * lineParams.x;
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm,
|
||||
uniforms.u_modelView, length(norm));
|
||||
if (lineParams.y != 0.0)
|
||||
len = float2(in.a_length.x + in.a_length.y * lineParams.y, in.a_length.z);
|
||||
}
|
||||
|
||||
out.lengthY = len.y;
|
||||
|
||||
float4 color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoords);
|
||||
color.a *= uniforms.u_opacity;
|
||||
out.color = color;
|
||||
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsSelectionLine(const SelectionLineFragment_T in [[stage_in]])
|
||||
{
|
||||
constexpr float kAntialiasingThreshold = 0.92;
|
||||
float4 color = in.color;
|
||||
color.a *= (1.0 - smoothstep(kAntialiasingThreshold, 1.0, abs(in.lengthY)));
|
||||
return color;
|
||||
}
|
||||
377
libs/shaders/Metal/smaa.metal
Normal file
377
libs/shaders/Metal/smaa.metal
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
// Implementation of Subpixel Morphological Antialiasing (SMAA) is based on https://github.com/iryoku/smaa
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 u_framebufferMetrics;
|
||||
} Uniforms_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_pos [[attribute(0)]];
|
||||
float2 a_tcoord [[attribute(1)]];
|
||||
} SmaaVertex_T;
|
||||
|
||||
// SmaaEdges
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 offset0;
|
||||
float4 offset1;
|
||||
float4 offset2;
|
||||
float2 coords;
|
||||
} SmaaEdgesFragment_T;
|
||||
|
||||
vertex SmaaEdgesFragment_T vsSmaaEdges(const SmaaVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
SmaaEdgesFragment_T out;
|
||||
|
||||
out.position = float4(in.a_pos, 0.0, 1.0);
|
||||
float2 tcoord = float2(in.a_tcoord.x, 1.0 - in.a_tcoord.y);
|
||||
out.coords = tcoord;
|
||||
float4 coords1 = uniforms.u_framebufferMetrics.xyxy;
|
||||
float4 coords2 = tcoord.xyxy;
|
||||
out.offset0 = coords1 * float4(-1.0, 0.0, 0.0, -1.0) + coords2;
|
||||
out.offset1 = coords1 * float4( 1.0, 0.0, 0.0, 1.0) + coords2;
|
||||
out.offset2 = coords1 * float4(-2.0, 0.0, 0.0, -2.0) + coords2;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// SMAA_THRESHOLD specifies the threshold or sensitivity to edges.
|
||||
// Lowering this value you will be able to detect more edges at the expense of
|
||||
// performance.
|
||||
// Range: [0, 0.5]
|
||||
// 0.1 is a reasonable value, and allows to catch most visible edges.
|
||||
// 0.05 is a rather overkill value, that allows to catch 'em all.
|
||||
#define SMAA_THRESHOLD 0.05
|
||||
constant float2 kThreshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD);
|
||||
|
||||
// If there is an neighbor edge that has SMAA_LOCAL_CONTRAST_FACTOR times
|
||||
// bigger contrast than current edge, current edge will be discarded.
|
||||
// This allows to eliminate spurious crossing edges, and is based on the fact
|
||||
// that, if there is too much contrast in a direction, that will hide
|
||||
// perceptually contrast in the other neighbors.
|
||||
#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0
|
||||
|
||||
// Standard relative luminance weights.
|
||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||
constant float3 kWeights = float3(0.2126, 0.7152, 0.0722);
|
||||
|
||||
fragment float4 fsSmaaEdges(const SmaaEdgesFragment_T in [[stage_in]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
// Calculate lumas.
|
||||
float L = dot(u_colorTex.sample(u_colorTexSampler, in.coords).rgb, kWeights);
|
||||
float Lleft = dot(u_colorTex.sample(u_colorTexSampler, in.offset0.xy).rgb, kWeights);
|
||||
float Ltop = dot(u_colorTex.sample(u_colorTexSampler, in.offset0.zw).rgb, kWeights);
|
||||
|
||||
// We do the usual threshold.
|
||||
float4 delta;
|
||||
delta.xy = abs(L - float2(Lleft, Ltop));
|
||||
float2 edges = step(kThreshold, delta.xy);
|
||||
if (dot(edges, float2(1.0, 1.0)) == 0.0)
|
||||
discard_fragment();
|
||||
|
||||
// Calculate right and bottom deltas.
|
||||
float Lright = dot(u_colorTex.sample(u_colorTexSampler, in.offset1.xy).rgb, kWeights);
|
||||
float Lbottom = dot(u_colorTex.sample(u_colorTexSampler, in.offset1.zw).rgb, kWeights);
|
||||
delta.zw = abs(L - float2(Lright, Lbottom));
|
||||
|
||||
// Calculate the maximum delta in the direct neighborhood.
|
||||
float2 maxDelta = max(delta.xy, delta.zw);
|
||||
|
||||
// Calculate left-left and top-top deltas.
|
||||
float Lleftleft = dot(u_colorTex.sample(u_colorTexSampler, in.offset2.xy).rgb, kWeights);
|
||||
float Ltoptop = dot(u_colorTex.sample(u_colorTexSampler, in.offset2.zw).rgb, kWeights);
|
||||
delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop));
|
||||
|
||||
// Calculate the final maximum delta.
|
||||
maxDelta = max(maxDelta.xy, delta.zw);
|
||||
float finalDelta = max(maxDelta.x, maxDelta.y);
|
||||
|
||||
// Local contrast adaptation.
|
||||
edges *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
|
||||
|
||||
return float4(edges, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// SmaaBlendingWeight
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 offset0;
|
||||
float4 offset1;
|
||||
float4 offset2;
|
||||
float4 coords;
|
||||
} SmaaBlendingWeightFragment_T;
|
||||
|
||||
// SMAA_MAX_SEARCH_STEPS specifies the maximum steps performed in the
|
||||
// horizontal/vertical pattern searches, at each side of the pixel.
|
||||
#define SMAA_MAX_SEARCH_STEPS 8.0
|
||||
constant float4 kMaxSearchSteps = float4(-2.0 * SMAA_MAX_SEARCH_STEPS, 2.0 * SMAA_MAX_SEARCH_STEPS,
|
||||
-2.0 * SMAA_MAX_SEARCH_STEPS, 2.0 * SMAA_MAX_SEARCH_STEPS);
|
||||
|
||||
vertex SmaaBlendingWeightFragment_T vsSmaaBlendingWeight(const SmaaVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
SmaaBlendingWeightFragment_T out;
|
||||
|
||||
out.position = float4(in.a_pos, 0.0, 1.0);
|
||||
float2 tcoord = float2(in.a_tcoord.x, 1.0 - in.a_tcoord.y);
|
||||
out.coords = float4(tcoord, tcoord * uniforms.u_framebufferMetrics.zw);
|
||||
// We will use these offsets for the searches.
|
||||
float4 coords1 = uniforms.u_framebufferMetrics.xyxy;
|
||||
float4 coords2 = tcoord.xyxy;
|
||||
out.offset0 = coords1 * float4(-0.25, -0.125, 1.25, -0.125) + coords2;
|
||||
out.offset1 = coords1 * float4(-0.125, -0.25, -0.125, 1.25) + coords2;
|
||||
// And these for the searches, they indicate the ends of the loops.
|
||||
out.offset2 = uniforms.u_framebufferMetrics.xxyy * kMaxSearchSteps + float4(out.offset0.xz, out.offset1.yw);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#define SMAA_SEARCHTEX_SIZE float2(66.0, 33.0)
|
||||
#define SMAA_SEARCHTEX_PACKED_SIZE float2(64.0, 16.0)
|
||||
#define SMAA_AREATEX_MAX_DISTANCE 16.0
|
||||
#define SMAA_AREATEX_PIXEL_SIZE (float2(1.0 / 256.0, 1.0 / 1024.0))
|
||||
|
||||
constant float2 kAreaTexMaxDistance = float2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE);
|
||||
constant float kActivationThreshold = 0.8281;
|
||||
|
||||
float SMAASearchLength(texture2d<float> u_smaaSearch, sampler u_smaaSearchSampler,
|
||||
float2 e, float offset)
|
||||
{
|
||||
// The texture is flipped vertically, with left and right cases taking half
|
||||
// of the space horizontally.
|
||||
float2 scale = SMAA_SEARCHTEX_SIZE * float2(0.5, -1.0);
|
||||
float2 bias = SMAA_SEARCHTEX_SIZE * float2(offset, 1.0);
|
||||
|
||||
// Scale and bias to access texel centers.
|
||||
scale += float2(-1.0, 1.0);
|
||||
bias += float2( 0.5, -0.5);
|
||||
|
||||
// Convert from pixel coordinates to texcoords.
|
||||
// (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped).
|
||||
scale *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE;
|
||||
bias *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE;
|
||||
|
||||
// Lookup the search texture.
|
||||
return u_smaaSearch.sample(u_smaaSearchSampler, scale * e + bias, level(0)).a;
|
||||
}
|
||||
|
||||
float SMAASearchXLeft(texture2d<float> u_colorTex, sampler u_colorTexSampler,
|
||||
texture2d<float> u_smaaSearch, sampler u_smaaSearchSampler,
|
||||
float2 texcoord, float end, float4 framebufferMetrics)
|
||||
{
|
||||
float2 e = float2(0.0, 1.0);
|
||||
while (texcoord.x > end && e.g > kActivationThreshold && e.r == 0.0)
|
||||
{
|
||||
e = u_colorTex.sample(u_colorTexSampler, texcoord, level(0)).rg;
|
||||
texcoord = float2(-2.0, 0.0) * framebufferMetrics.xy + texcoord;
|
||||
}
|
||||
float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(u_smaaSearch, u_smaaSearchSampler, e, 0.0);
|
||||
return framebufferMetrics.x * offset + texcoord.x;
|
||||
}
|
||||
|
||||
float SMAASearchXRight(texture2d<float> u_colorTex, sampler u_colorTexSampler,
|
||||
texture2d<float> u_smaaSearch, sampler u_smaaSearchSampler,
|
||||
float2 texcoord, float end, float4 framebufferMetrics)
|
||||
{
|
||||
float2 e = float2(0.0, 1.0);
|
||||
while (texcoord.x < end && e.g > kActivationThreshold && e.r == 0.0)
|
||||
{
|
||||
e = u_colorTex.sample(u_colorTexSampler, texcoord, level(0)).rg;
|
||||
texcoord = float2(2.0, 0.0) * framebufferMetrics.xy + texcoord;
|
||||
}
|
||||
float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(u_smaaSearch, u_smaaSearchSampler, e, 0.5);
|
||||
return -framebufferMetrics.x * offset + texcoord.x;
|
||||
}
|
||||
|
||||
float SMAASearchYUp(texture2d<float> u_colorTex, sampler u_colorTexSampler,
|
||||
texture2d<float> u_smaaSearch, sampler u_smaaSearchSampler,
|
||||
float2 texcoord, float end, float4 framebufferMetrics)
|
||||
{
|
||||
float2 e = float2(1.0, 0.0);
|
||||
while (texcoord.y > end && e.r > kActivationThreshold && e.g == 0.0)
|
||||
{
|
||||
e = u_colorTex.sample(u_colorTexSampler, texcoord, level(0)).rg;
|
||||
texcoord = float2(0.0, -2.0) * framebufferMetrics.xy + texcoord;
|
||||
}
|
||||
float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(u_smaaSearch, u_smaaSearchSampler, e.gr, 0.0);
|
||||
return framebufferMetrics.y * offset + texcoord.y;
|
||||
}
|
||||
|
||||
float SMAASearchYDown(texture2d<float> u_colorTex, sampler u_colorTexSampler,
|
||||
texture2d<float> u_smaaSearch, sampler u_smaaSearchSampler,
|
||||
float2 texcoord, float end, float4 framebufferMetrics)
|
||||
{
|
||||
float2 e = float2(1.0, 0.0);
|
||||
while (texcoord.y < end && e.r > kActivationThreshold && e.g == 0.0)
|
||||
{
|
||||
e = u_colorTex.sample(u_colorTexSampler, texcoord, level(0)).rg;
|
||||
texcoord = float2(0.0, 2.0) * framebufferMetrics.xy + texcoord;
|
||||
}
|
||||
float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(u_smaaSearch, u_smaaSearchSampler, e.gr, 0.5);
|
||||
return -framebufferMetrics.y * offset + texcoord.y;
|
||||
}
|
||||
|
||||
// Here, we have the distance and both crossing edges. So, what are the areas
|
||||
// at each side of current edge?
|
||||
float2 SMAAArea(texture2d<float> u_smaaArea, sampler u_smaaAreaSampler, float2 dist, float e1, float e2)
|
||||
{
|
||||
// Rounding prevents precision errors of bilinear filtering.
|
||||
float2 texcoord = kAreaTexMaxDistance * round(4.0 * float2(e1, e2)) + dist;
|
||||
// We do a scale and bias for mapping to texel space.
|
||||
texcoord = SMAA_AREATEX_PIXEL_SIZE * (texcoord + 0.5);
|
||||
return u_smaaArea.sample(u_smaaAreaSampler, texcoord, level(0)).rg;
|
||||
}
|
||||
|
||||
fragment float4 fsSmaaBlendingWeight(const SmaaBlendingWeightFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]],
|
||||
texture2d<float> u_smaaArea [[texture(1)]],
|
||||
sampler u_smaaAreaSampler [[sampler(1)]],
|
||||
texture2d<float> u_smaaSearch [[texture(2)]],
|
||||
sampler u_smaaSearchSampler [[sampler(2)]])
|
||||
{
|
||||
float4 weights = float4(0.0, 0.0, 0.0, 0.0);
|
||||
float2 e = u_colorTex.sample(u_colorTexSampler, in.coords.xy).rg;
|
||||
|
||||
if (e.g > 0.0) // Edge at north
|
||||
{
|
||||
float2 d;
|
||||
|
||||
// Find the distance to the left.
|
||||
float3 coords;
|
||||
coords.x = SMAASearchXLeft(u_colorTex, u_colorTexSampler, u_smaaSearch, u_smaaSearchSampler,
|
||||
in.offset0.xy, in.offset2.x, uniforms.u_framebufferMetrics);
|
||||
coords.y = in.offset1.y;
|
||||
d.x = coords.x;
|
||||
|
||||
// Now fetch the left crossing edges, two at a time using bilinear
|
||||
// filtering. Sampling at -0.25 enables to discern what value each edge has.
|
||||
float e1 = u_colorTex.sample(u_colorTexSampler, coords.xy, level(0)).r;
|
||||
|
||||
// Find the distance to the right.
|
||||
coords.z = SMAASearchXRight(u_colorTex, u_colorTexSampler, u_smaaSearch, u_smaaSearchSampler,
|
||||
in.offset0.zw, in.offset2.y, uniforms.u_framebufferMetrics);
|
||||
d.y = coords.z;
|
||||
|
||||
// We want the distances to be in pixel units (doing this here allow to
|
||||
// better interleave arithmetic and memory accesses).
|
||||
d = abs(round(uniforms.u_framebufferMetrics.zz * d - in.coords.zz));
|
||||
|
||||
// SMAAArea below needs a sqrt, as the areas texture is compressed
|
||||
// quadratically.
|
||||
float2 sqrtD = sqrt(d);
|
||||
|
||||
// Fetch the right crossing edges.
|
||||
float e2 = u_colorTex.sample(u_colorTexSampler, coords.zy, level(0), int2(1, 0)).r;
|
||||
|
||||
// Here we know how this pattern looks like, now it is time for getting
|
||||
// the actual area.
|
||||
weights.rg = SMAAArea(u_smaaArea, u_smaaAreaSampler, sqrtD, e1, e2);
|
||||
}
|
||||
|
||||
if (e.r > 0.0) // Edge at west
|
||||
{
|
||||
float2 d;
|
||||
|
||||
// Find the distance to the top.
|
||||
float3 coords;
|
||||
coords.y = SMAASearchYUp(u_colorTex, u_colorTexSampler, u_smaaSearch, u_smaaSearchSampler,
|
||||
in.offset1.xy, in.offset2.z, uniforms.u_framebufferMetrics);
|
||||
coords.x = in.offset0.x;
|
||||
d.x = coords.y;
|
||||
|
||||
// Fetch the top crossing edges.
|
||||
float e1 = u_colorTex.sample(u_colorTexSampler, coords.xy, level(0)).g;
|
||||
|
||||
// Find the distance to the bottom.
|
||||
coords.z = SMAASearchYDown(u_colorTex, u_colorTexSampler, u_smaaSearch, u_smaaSearchSampler,
|
||||
in.offset1.zw, in.offset2.w, uniforms.u_framebufferMetrics);
|
||||
d.y = coords.z;
|
||||
|
||||
// We want the distances to be in pixel units.
|
||||
d = abs(round(uniforms.u_framebufferMetrics.ww * d - in.coords.ww));
|
||||
|
||||
// SMAAArea below needs a sqrt, as the areas texture is compressed
|
||||
// quadratically.
|
||||
float2 sqrtD = sqrt(d);
|
||||
|
||||
// Fetch the bottom crossing edges.
|
||||
float e2 = u_colorTex.sample(u_colorTexSampler, coords.xz, level(0), int2(0, 1)).g;
|
||||
|
||||
// Get the area for this direction.
|
||||
weights.ba = SMAAArea(u_smaaArea, u_smaaAreaSampler, sqrtD, e1, e2);
|
||||
}
|
||||
|
||||
return weights;
|
||||
}
|
||||
|
||||
// SmaaFinal
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 offset;
|
||||
float2 texCoords;
|
||||
} SmaaFinalFragment_T;
|
||||
|
||||
vertex SmaaFinalFragment_T vsSmaaFinal(const SmaaVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
SmaaFinalFragment_T out;
|
||||
float2 tcoord = float2(in.a_tcoord.x, 1.0 - in.a_tcoord.y);
|
||||
out.position = float4(in.a_pos, 0.0, 1.0);
|
||||
out.offset = uniforms.u_framebufferMetrics.xyxy * float4(1.0, 0.0, 0.0, 1.0) + tcoord.xyxy;
|
||||
out.texCoords = tcoord;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsSmaaFinal(const SmaaFinalFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]],
|
||||
texture2d<float> u_blendingWeightTex [[texture(1)]],
|
||||
sampler u_blendingWeightTexSampler [[sampler(1)]])
|
||||
{
|
||||
// Fetch the blending weights for current pixel.
|
||||
float4 a;
|
||||
a.x = u_blendingWeightTex.sample(u_blendingWeightTexSampler, in.offset.xy).a; // Right
|
||||
a.y = u_blendingWeightTex.sample(u_blendingWeightTexSampler, in.offset.zw).g; // Top
|
||||
a.wz = u_blendingWeightTex.sample(u_blendingWeightTexSampler, in.texCoords).xz; // Bottom / Left
|
||||
|
||||
// Is there any blending weight with a value greater than 0.0?
|
||||
if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5)
|
||||
return u_colorTex.sample(u_colorTexSampler, in.texCoords);
|
||||
|
||||
// Calculate the blending offsets.
|
||||
float4 blendingOffset = float4(0.0, a.y, 0.0, a.w);
|
||||
float2 blendingWeight = a.yw;
|
||||
if (max(a.x, a.z) > max(a.y, a.w))
|
||||
{
|
||||
blendingOffset = float4(a.x, 0.0, a.z, 0.0);
|
||||
blendingWeight = a.xz;
|
||||
}
|
||||
blendingWeight /= dot(blendingWeight, float2(1.0, 1.0));
|
||||
|
||||
// Calculate the texture coordinates.
|
||||
float4 bc = blendingOffset * float4(uniforms.u_framebufferMetrics.xy, -uniforms.u_framebufferMetrics.xy);
|
||||
bc += in.texCoords.xyxy;
|
||||
|
||||
// We exploit bilinear filtering to mix current pixel with the chosen neighbor.
|
||||
float4 color = blendingWeight.x * u_colorTex.sample(u_colorTexSampler, bc.xy, level(0));
|
||||
color += blendingWeight.y * u_colorTex.sample(u_colorTexSampler, bc.zw, level(0));
|
||||
return color;
|
||||
}
|
||||
58
libs/shaders/Metal/system.metal
Normal file
58
libs/shaders/Metal/system.metal
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float2 a_position [[attribute(0)]];
|
||||
} Vertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
} Fragment_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 u_color;
|
||||
} Uniforms_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} Fragment_Output;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float depth [[depth(any)]];
|
||||
} Fragment_DepthOutput;
|
||||
|
||||
vertex Fragment_T vsCleaner(const Vertex_T in [[stage_in]])
|
||||
{
|
||||
Fragment_T out;
|
||||
out.position = float4(in.a_position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsClearColor(const Fragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
return uniforms.u_color;
|
||||
}
|
||||
|
||||
fragment Fragment_DepthOutput fsClearDepth(const Fragment_T in [[stage_in]])
|
||||
{
|
||||
Fragment_DepthOutput out;
|
||||
out.depth = 1.0;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment Fragment_Output fsClearColorAndDepth(const Fragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
Fragment_Output out;
|
||||
out.color = uniforms.u_color;
|
||||
out.depth = 1.0;
|
||||
return out;
|
||||
}
|
||||
208
libs/shaders/Metal/traffic.metal
Normal file
208
libs/shaders/Metal/traffic.metal
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
#include "shaders_lib.h"
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_modelView;
|
||||
float4x4 u_projection;
|
||||
float4x4 u_pivotTransform;
|
||||
float4 u_trafficParams;
|
||||
packed_float3 u_outlineColor;
|
||||
float u_dummy1; // alignment
|
||||
packed_float3 u_lightArrowColor;
|
||||
float u_dummy2; // alignment
|
||||
packed_float3 u_darkArrowColor;
|
||||
float u_dummy3; // alignment
|
||||
float u_outline;
|
||||
float u_opacity;
|
||||
} Uniforms_T;
|
||||
|
||||
// Traffic
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float4 a_normal [[attribute(1)]];
|
||||
float4 a_colorTexCoord [[attribute(2)]];
|
||||
} TrafficVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
float2 maskTexCoord;
|
||||
float halfLength;
|
||||
} TrafficFragment_T;
|
||||
|
||||
vertex TrafficFragment_T vsTraffic(const TrafficVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
constexpr float kArrowVSize = 0.25;
|
||||
|
||||
TrafficFragment_T out;
|
||||
|
||||
float2 normal = in.a_normal.xy;
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
if (dot(normal, normal) != 0.0)
|
||||
{
|
||||
float2 norm = normal * uniforms.u_trafficParams.x;
|
||||
if (in.a_normal.z < 0.0)
|
||||
norm = normal * uniforms.u_trafficParams.y;
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm,
|
||||
uniforms.u_modelView, length(norm));
|
||||
}
|
||||
|
||||
float uOffset = length(float4(kShapeCoordScalar, 0.0, 0.0, 0.0) * uniforms.u_modelView) * in.a_normal.w;
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord.xy);
|
||||
float v = mix(in.a_colorTexCoord.z, in.a_colorTexCoord.z + kArrowVSize, 0.5 * in.a_normal.z + 0.5);
|
||||
out.maskTexCoord = float2(uOffset * uniforms.u_trafficParams.z, v) * uniforms.u_trafficParams.w;
|
||||
out.maskTexCoord.x *= step(in.a_colorTexCoord.w, out.maskTexCoord.x);
|
||||
out.halfLength = in.a_normal.z;
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsTraffic(const TrafficFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]],
|
||||
texture2d<float> u_maskTex [[texture(0)]],
|
||||
sampler u_maskTexSampler [[sampler(0)]])
|
||||
{
|
||||
constexpr float kAntialiasingThreshold = 0.92;
|
||||
|
||||
constexpr float kOutlineThreshold1 = 0.8;
|
||||
constexpr float kOutlineThreshold2 = 0.5;
|
||||
|
||||
constexpr float kMaskOpacity = 0.7;
|
||||
|
||||
float4 color = in.color;
|
||||
float alphaCode = color.a;
|
||||
float4 mask = u_maskTex.sample(u_maskTexSampler, in.maskTexCoord);
|
||||
color.a = uniforms.u_opacity * (1.0 - smoothstep(kAntialiasingThreshold, 1.0, abs(in.halfLength)));
|
||||
color.rgb = mix(color.rgb, mask.rgb * mix(uniforms.u_lightArrowColor, uniforms.u_darkArrowColor, step(alphaCode, 0.6)), mask.a * kMaskOpacity);
|
||||
if (uniforms.u_outline > 0.0)
|
||||
{
|
||||
float3 outlineColor = uniforms.u_outlineColor;
|
||||
color.rgb = mix(color.rgb, outlineColor, step(kOutlineThreshold1, abs(in.halfLength)));
|
||||
color.rgb = mix(color.rgb, outlineColor, smoothstep(kOutlineThreshold2, kOutlineThreshold1, abs(in.halfLength)));
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// TrafficLine
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float2 a_colorTexCoord [[attribute(1)]];
|
||||
} TrafficLineVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
} TrafficLineFragment_T;
|
||||
|
||||
vertex TrafficLineFragment_T vsTrafficLine(const TrafficLineVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
TrafficLineFragment_T out;
|
||||
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.color = float4(u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord).rgb, uniforms.u_opacity);
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsTrafficLine(const TrafficLineFragment_T in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
}
|
||||
|
||||
// TrafficCircle
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 a_position [[attribute(0)]];
|
||||
float4 a_normal [[attribute(1)]];
|
||||
float2 a_colorTexCoord [[attribute(2)]];
|
||||
} TrafficCircleVertex_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
float3 radius;
|
||||
} TrafficCircleFragment_T;
|
||||
|
||||
vertex TrafficCircleFragment_T vsTrafficCircle(const TrafficCircleVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]],
|
||||
texture2d<float> u_colorTex [[texture(0)]],
|
||||
sampler u_colorTexSampler [[sampler(0)]])
|
||||
{
|
||||
TrafficCircleFragment_T out;
|
||||
|
||||
float2 normal = in.a_normal.xy;
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
int index = int(in.a_position.w);
|
||||
|
||||
float3 leftSizes = uniforms.u_lightArrowColor;
|
||||
float leftSize = leftSizes[index];
|
||||
|
||||
float3 rightSizes = uniforms.u_darkArrowColor;
|
||||
float rightSize = rightSizes[index];
|
||||
|
||||
if (dot(normal, normal) != 0.0)
|
||||
{
|
||||
// offset by normal = rightVec * (rightSize - leftSize) / 2
|
||||
float2 norm = normal * 0.5 * (rightSize - leftSize);
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm,
|
||||
uniforms.u_modelView, length(norm));
|
||||
}
|
||||
// radius = (leftSize + rightSize) / 2
|
||||
out.radius = float3(in.a_normal.zw, 1.0) * 0.5 * (leftSize + rightSize);
|
||||
|
||||
float2 finalPos = transformedAxisPos + out.radius.xy;
|
||||
out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord);
|
||||
float4 pos = float4(finalPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} TrafficCircleOut_T;
|
||||
|
||||
fragment TrafficCircleOut_T fsTrafficCircle(const TrafficCircleFragment_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(0)]])
|
||||
{
|
||||
constexpr float kAntialiasingThreshold = 0.92;
|
||||
|
||||
TrafficCircleOut_T out;
|
||||
|
||||
float4 color = in.color;
|
||||
|
||||
float smallRadius = in.radius.z * kAntialiasingThreshold;
|
||||
float stepValue = smoothstep(smallRadius * smallRadius, in.radius.z * in.radius.z,
|
||||
in.radius.x * in.radius.x + in.radius.y * in.radius.y);
|
||||
color.a = uniforms.u_opacity * (1.0 - stepValue);
|
||||
if (color.a < 0.001)
|
||||
out.depth = 1.0;
|
||||
else
|
||||
out.depth = in.position.z * in.position.w;
|
||||
out.color = color;
|
||||
return out;
|
||||
}
|
||||
155
libs/shaders/Metal/transit.metal
Normal file
155
libs/shaders/Metal/transit.metal
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
#include "shaders_lib.h"
|
||||
using namespace metal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 u_modelView;
|
||||
float4x4 u_projection;
|
||||
float4x4 u_pivotTransform;
|
||||
packed_float3 u_params;
|
||||
float u_dummy1;
|
||||
float u_lineHalfWidth;
|
||||
float u_maxRadius;
|
||||
} Uniforms_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float3 a_position [[attribute(0)]];
|
||||
float4 a_normal [[attribute(1)]];
|
||||
float4 a_color [[attribute(2)]];
|
||||
} TransitVertex_T;
|
||||
|
||||
// Transit
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
} TransitFragment_T;
|
||||
|
||||
vertex TransitFragment_T vsTransit(const TransitVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
TransitFragment_T out;
|
||||
|
||||
float2 normal = in.a_normal.xy;
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
if (dot(normal, normal) != 0.0)
|
||||
{
|
||||
float2 norm = normal * uniforms.u_lineHalfWidth;
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm,
|
||||
uniforms.u_modelView, length(norm));
|
||||
}
|
||||
out.color = in.a_color;
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsTransit(const TransitFragment_T in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
}
|
||||
|
||||
// Transit marker
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 offsets;
|
||||
float4 color;
|
||||
} TransitMarkerFragment_T;
|
||||
|
||||
vertex TransitMarkerFragment_T vsTransitMarker(const TransitVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
TransitMarkerFragment_T out;
|
||||
|
||||
float4 pos = float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView;
|
||||
float3 params = uniforms.u_params;
|
||||
float2 normal = float2(in.a_normal.x * params.x - in.a_normal.y * params.y,
|
||||
in.a_normal.x * params.y + in.a_normal.y * params.x);
|
||||
float2 shiftedPos = normal * params.z + pos.xy;
|
||||
pos = float4(shiftedPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
|
||||
float2 offsets = abs(in.a_normal.zw);
|
||||
out.offsets = float4(in.a_normal.zw, offsets - 1.0);
|
||||
out.color = in.a_color;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fsTransitMarker(const TransitMarkerFragment_T in [[stage_in]])
|
||||
{
|
||||
float4 finalColor = in.color;
|
||||
float2 radius;
|
||||
radius.x = max(0.0, abs(in.offsets.x) - in.offsets.z);
|
||||
radius.y = max(0.0, abs(in.offsets.y) - in.offsets.w);
|
||||
|
||||
float maxRadius = 1.0;
|
||||
float aaRadius = 0.9;
|
||||
float stepValue = 1.0 - smoothstep(aaRadius * aaRadius, maxRadius * maxRadius, dot(radius.xy, radius.xy));
|
||||
finalColor.a *= stepValue;
|
||||
|
||||
return finalColor;
|
||||
}
|
||||
|
||||
// Transit circle
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 position [[position]];
|
||||
float3 radius;
|
||||
float4 color;
|
||||
} TransitCircleFragment_T;
|
||||
|
||||
vertex TransitCircleFragment_T vsTransitCircle(const TransitVertex_T in [[stage_in]],
|
||||
constant Uniforms_T & uniforms [[buffer(1)]])
|
||||
{
|
||||
TransitCircleFragment_T out;
|
||||
|
||||
float2 normal = in.a_normal.xy;
|
||||
float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy;
|
||||
if (dot(normal, normal) != 0.0)
|
||||
{
|
||||
float2 norm = normal * uniforms.u_lineHalfWidth;
|
||||
transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm,
|
||||
uniforms.u_modelView, length(norm));
|
||||
}
|
||||
transformedAxisPos += in.a_normal.zw * uniforms.u_lineHalfWidth;
|
||||
float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection;
|
||||
out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0);
|
||||
out.color = in.a_color;
|
||||
out.radius = float3(in.a_normal.zw, uniforms.u_maxRadius) * uniforms.u_lineHalfWidth;
|
||||
return out;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 color [[color(0)]];
|
||||
float depth [[depth(any)]];
|
||||
} TransitCircleOut_T;
|
||||
|
||||
fragment TransitCircleOut_T fsTransitCircle(const TransitCircleFragment_T in [[stage_in]])
|
||||
{
|
||||
constexpr float kAntialiasingPixelsCount = 2.5;
|
||||
|
||||
TransitCircleOut_T out;
|
||||
|
||||
float4 finalColor = in.color;
|
||||
|
||||
float smallRadius = in.radius.z - kAntialiasingPixelsCount;
|
||||
float stepValue = smoothstep(smallRadius * smallRadius, in.radius.z * in.radius.z,
|
||||
dot(in.radius.xy, in.radius.xy));
|
||||
finalColor.a = finalColor.a * (1.0 - stepValue);
|
||||
if (finalColor.a < 0.001)
|
||||
out.depth = 1.0;
|
||||
else
|
||||
out.depth = in.position.z * in.position.w;
|
||||
|
||||
out.color = finalColor;
|
||||
|
||||
return out;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue