2 рдбреА рдореЗрдВ рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рджреВрд░реА рдХреЗ рдХреНрд╖реЗрддреНрд░

рдкрд┐рдЫрд▓реЗ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ, рд╣рдордиреЗ рд╕реАрдЦрд╛ рдХрд┐ рдХреИрд╕реЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рджреВрд░реА рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░рд▓ рдЖрдХреГрддрд┐рдпреЛрдВ рдХреЛ рдмрдирд╛рдпрд╛ рдФрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рд╕реАрдЦреЗрдВрдЧреЗ рдХрд┐ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рджреВрд░реА рд╡рд╛рд▓реЗ рдлрд╝реАрд▓реНрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдЖрдХреГрддрд┐рдпреЛрдВ рдХреЛ рдХреИрд╕реЗ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред рдореИрдВрдиреЗ рджреВрд░рд╕реНрде рдХрд╛рд░реНрдпреЛрдВ рдХреЗ glsl-sign рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реЗ рдпрд╣рд╛рдВ рд╡рд░реНрдгрд┐рдд рдЕрдзрд┐рдХрд╛рдВрд╢ рддрдХрдиреАрдХреЛрдВ рдХреЛ рд╕реАрдЦрд╛, рдЬреЛ рдпрд╣рд╛рдВ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИрдВ ред рдЖрдХреГрддрд┐рдпреЛрдВ рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рднреА рд╣реИрдВ, рдЬрд┐рдирдХреА рдореИрдВ рдпрд╣рд╛рдБ рдЪрд░реНрдЪрд╛ рдирд╣реАрдВ рдХрд░рддрд╛ред


рдЯреНрд░реЗрдирд┐рдВрдЧ


рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рджреВрд░реА рдХреНрд╖реЗрддреНрд░реЛрдВ (рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рджреВрд░реА рдХреНрд╖реЗрддреНрд░реЛрдВ, рдПрд╕рдбреАрдПрдл) рдХреЗ рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдлрд┐рд░ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЛ рдЙрд╕ рдкрд░ рд▓рд╛рдЧреВ рдХрд░реЗрдВрдЧреЗред рджреВрд░рд╕реНрде рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдкрд╣рд▓реЗ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рд╕реЗ рджреВрд░реА рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рджреГрд╢реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛ред рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо рдХреЛрдб рдореЗрдВ рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рднреА рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реЗрдЯ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЖрдк рдЗрд╕реЗ рдЕрдиреБрдХреВрд▓рди рдпреЛрдЧреНрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдореВрд▓реНрдп рдХреЛ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рд╕рд╛рде рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред

рдореБрдЦреНрдп shader рд╣рдо рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдЧрд╛:

Shader "Tutorial/035_2D_SDF_Combinations/Champfer Union"{ Properties{ _InsideColor("Inside Color", Color) = (.5, 0, 0, 1) _OutsideColor("Outside Color", Color) = (0, .5, 0, 1) _LineDistance("Mayor Line Distance", Range(0, 2)) = 1 _LineThickness("Mayor Line Thickness", Range(0, 0.1)) = 0.05 [IntRange]_SubLines("Lines between major lines", Range(1, 10)) = 4 _SubLineThickness("Thickness of inbetween lines", Range(0, 0.05)) = 0.01 } SubShader{ //the material is completely non-transparent and is rendered at the same time as the other opaque geometry Tags{ "RenderType"="Opaque" "Queue"="Geometry"} Pass{ CGPROGRAM #include "UnityCG.cginc" #include "2D_SDF.cginc" #pragma vertex vert #pragma fragment frag struct appdata{ float4 vertex : POSITION; }; struct v2f{ float4 position : SV_POSITION; float4 worldPos : TEXCOORD0; }; v2f vert(appdata v){ v2f o; //calculate the position in clip space to render the object o.position = UnityObjectToClipPos(v.vertex); //calculate world position of vertex o.worldPos = mul(unity_ObjectToWorld, v.vertex); return o; } float scene(float2 position) { const float PI = 3.14159; float2 squarePosition = position; squarePosition = translate(squarePosition, float2(1, 0)); squarePosition = rotate(squarePosition, .125); float squareShape = rectangle(squarePosition, float2(2, 2)); float2 circlePosition = position; circlePosition = translate(circlePosition, float2(-1.5, 0)); float circleShape = circle(circlePosition, 2.5); float combination = combination_function(circleShape, squareShape); return combination; } float4 _InsideColor; float4 _OutsideColor; float _LineDistance; float _LineThickness; float _SubLines; float _SubLineThickness; fixed4 frag(v2f i) : SV_TARGET{ float dist = scene(i.worldPos.xz); fixed4 col = lerp(_InsideColor, _OutsideColor, step(0, dist)); float distanceChange = fwidth(dist) * 0.5; float majorLineDistance = abs(frac(dist / _LineDistance + 0.5) - 0.5) * _LineDistance; float majorLines = smoothstep(_LineThickness - distanceChange, _LineThickness + distanceChange, majorLineDistance); float distanceBetweenSubLines = _LineDistance / _SubLines; float subLineDistance = abs(frac(dist / distanceBetweenSubLines + 0.5) - 0.5) * distanceBetweenSubLines; float subLines = smoothstep(_SubLineThickness - distanceChange, _SubLineThickness + distanceChange, subLineDistance); return col * majorLines * subLines; } ENDCG } } FallBack "Standard" //fallback adds a shadow pass so we get shadows on other objects } 

рдФрд░ shader рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ 2D_SDF.cginc рдлрд╝рдВрдХреНрд╢рди, рдЬрд┐рд╕реЗ рд╣рдо рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░реЗрдВрдЧреЗ, рдкрд╣рд▓реЗ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

 #ifndef SDF_2D #define SDF_2D //transforms float2 rotate(float2 samplePosition, float rotation){ const float PI = 3.14159; float angle = rotation * PI * 2 * -1; float sine, cosine; sincos(angle, sine, cosine); return float2(cosine * samplePosition.x + sine * samplePosition.y, cosine * samplePosition.y - sine * samplePosition.x); } float2 translate(float2 samplePosition, float2 offset){ //move samplepoint in the opposite direction that we want to move shapes in return samplePosition - offset; } float2 scale(float2 samplePosition, float scale){ return samplePosition / scale; } //shapes float circle(float2 samplePosition, float radius){ //get distance from center and grow it according to radius return length(samplePosition) - radius; } float rectangle(float2 samplePosition, float2 halfSize){ float2 componentWiseEdgeDistance = abs(samplePosition) - halfSize; float outsideDistance = length(max(componentWiseEdgeDistance, 0)); float insideDistance = min(max(componentWiseEdgeDistance.x, componentWiseEdgeDistance.y), 0); return outsideDistance + insideDistance; } #endif 

рд╕рд░рд▓ рд╕рдВрдпреЛрдЬрди


рд╣рдо рджреЛ рдмрдбрд╝реЗ рдЖрдХрд╛рд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕рд░рд▓ рддрд░реАрдХреЛрдВ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗ, рдПрдХ рдмрдбрд╝рд╛ рдЖрдХрд╛рд░, рд╕рдВрдпреБрдЧреНрдорди, рдЪреМрд░рд╛рд╣рд╛ рдФрд░ рдШрдЯрд╛рд╡ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рд╛рде рд╣реА рдПрдХ рдЖрдХрд╛рд░ рдХреЛ рджреВрд╕рд░реЗ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдПред

рд╡рд┐рдХрд╛рд░


рд╕рд░рд▓рддрдо рдСрдкрд░реЗрдЯрд░ рдпреБрдЧреНрдорди рд╣реИред рдЗрд╕рдХреЗ рд╕рд╛рде, рд╣рдо рджреЛ рдЖрдВрдХрдбрд╝реЗ рдПрдХ рд╕рд╛рде рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЬреБрдбрд╝реЗ рд╣реБрдП рдЖрдВрдХрдбрд╝реЗ рдХреЗ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рджреВрд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдХреЗ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рдПрдХ рджреВрд░реА рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо min рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджреЛрдиреЛрдВ рдХреЛ рдЫреЛрдЯрд╛ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред

рджреЛ рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рд╕реЗ рдЫреЛрдЯреЗ рдХреА рдкрд╕рдВрдж рдХреЗ рдХрд╛рд░рдг, рдЕрдВрддрд┐рдо рдЖрдВрдХрдбрд╝рд╛ 0 рд╕реЗ рдиреАрдЪреЗ (рджреГрд╢реНрдпрдорд╛рди) рд╣реЛрдЧрд╛ рдЬрд╣рд╛рдВ рджреЛ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЖрдВрдХрдбрд╝реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рдХрд┐рдирд╛рд░реЗ рдХреА рджреВрд░реА 0 рд╕реЗ рдХрдо рд╣реИ; рд╡рд╣реА рдЕрдиреНрдп рд╕рднреА рджреВрд░реА рдХреЗ рдореВрд▓реНрдпреЛрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рджреЛ рдЖрдВрдХрдбрд╝реЗ рдХрд╛ рд╕рдВрдпреЛрдЬрди рд╣реЛрддрд╛ рд╣реИред

рдпрд╣рд╛рдВ рдореИрдВ рд╕рдВрдпреБрдЧреНрдорди "рдорд░реНрдЬ" рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд╛рдо рджреВрдВрдЧрд╛, рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╡рд┐рд▓рдп рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдХреНрдпреЛрдВрдХрд┐ hlsl рдореЗрдВ рдпреВрдирд┐рдпрди рдХреАрд╡рд░реНрдб рдЖрд░рдХреНрд╖рд┐рдд рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдирд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

 //in 2D_SDF.cginc include file float merge(float shape1, float shape2){ return min(shape1, shape2); } 

 //in scene function in shader float combination = merge(circleShape, squareShape); 




рдЪреМрд░рд╛рд╣рд╛


рдЖрдХреГрддрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдПрдХ рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХрд╛ рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рдЬрд┐рдирдореЗрдВ рджреЛ рдЖрдХреГрддрд┐рдпрд╛рдБ рдУрд╡рд░рд▓реИрдк рд╣реЛрддреА рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрди рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдХреА рджреВрд░реА рдХрд╛ рдЕрдзрд┐рдХрддрдо рдореВрд▓реНрдп рд▓реЗрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рджреЛ рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рд╕реЗ рд╕рдмрд╕реЗ рдмрдбрд╝реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рд╣рдо 0 (рдЖрдВрдХрдбрд╝рд╛ рдХреЗ рдмрд╛рд╣рд░) рд╕реЗ рдЕрдзрд┐рдХ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрдм рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рджреВрд░реА рдЖрдВрдХрдбрд╝реЗ рдХреЗ рдмрд╛рд╣рд░ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЕрдиреНрдп рджреВрд░рд┐рдпрд╛рдВ рднреА рдЗрд╕реА рддрд░рд╣ рд╕реЗ рдКрдкрд░ рдкрдВрдХреНрддрд┐рдмрджреНрдз рд╣реЛрддреА рд╣реИрдВред

 //in 2D_SDF.cginc include file float intersect(float shape1, float shape2){ return max(shape1, shape2); } 

 //in scene function in shader float combination = intersect(circleShape, squareShape); 


рдШрдЯрд╛рд╡


рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЕрдХреНрд╕рд░ рд╣рдо рджреЛрдиреЛрдВ рдЖрдХрд╛рд░реЛрдВ рдХреЛ рдПрдХ рд╣реА рддрд░рд╣ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рд╣рдореЗрдВ рджреВрд╕рд░реЗ рдХреЛ рдПрдХ рдЖрдХрд╛рд░ рд╕реЗ рдШрдЯрд╛рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдЙрд╕ рдЖрдХрд╛рд░ рдХреЗ рдмреАрдЪ рдореЗрдВ рдЕрдВрддрд░ рдХрд░рдХреЗ рдХрд░рдирд╛ рдХрд╛рдлреА рдЖрд╕рд╛рди рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдмрджрд▓рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдФрд░ рд╡рд╣ рд╕рднреА рдЖрдХрд╛рд░ рдЬреЛ рд╣рдо рдШрдЯрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рд╣рдо рдЖрдХреГрддрд┐ рдХреЗ рдЖрдВрддрд░рд┐рдХ рдФрд░ рдмрд╛рд╣рд░реА рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рдкрд░реАрдд рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рджреВрд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред рдЖрдВрдХрдбрд╝рд╛ рдХреЗ рдмрд╛рд╣рд░ 1 рдпреВрдирд┐рдЯ рдХреНрдпрд╛ рдерд╛ рдЕрдм 1 рдпреВрдирд┐рдЯ рдЕрдВрджрд░ рд╣реИред

 //in 2D_SDF.cginc include file float subtract(float base, float subtraction){ return intersect(base, -subtraction); } 

 //in scene function in shader float combination = subtract(squareShape, circleShape); 


рдкреНрд░рдХреНрд╖реЗрдк


рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдХреЛ рдорд┐рд▓рд╛рдиреЗ рдХрд╛ рдПрдХ рдирд╛рдпрд╛рдм рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдЖрдкрд╕ рдореЗрдВ рдмрд╛рддрдЪреАрдд рдХрд░реЗрдВред рдпрд╣ рдмреНрд▓реЗрдВрдбрд╢рд╛реЕрдк рдХреЗ рд╕рд╛рде рдмрд╣реБрднреБрдЬ рдореЗрд╢ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╣рдж рддрдХ рднреА рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд рджреВрд░реА рдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рд╣рдо рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕реАрдорд┐рдд рд╣реИред рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдХреА рджреВрд░рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рд╕рд░рд▓ рдкреНрд░рдХреНрд╖реЗрдк рд╕реЗ, рд╣рдо рдПрдХ рджреВрд╕рд░реЗ рдореЗрдВ рдПрдХ рд╕рд╣рдЬ рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред рдкреНрд░рдХреНрд╖реЗрдк рдХреЗ рд▓рд┐рдП, рдЖрдк рдмрд╕ lerp рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

 //in 2D_SDF.cginc include file float interpolate(float shape1, float shape2, float amount){ return lerp(shape1, shape2, amount); } 

 //in scene function in shader float pulse = sin(_Time.y) * 0.5 + 0.5; float combination = interpolate(circleShape, pulse); 


рдЕрдиреНрдп рдпреМрдЧрд┐рдХ


рд╕рд░рд▓ рдХрдиреЗрдХреНрд╢рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЖрдВрдХрдбрд╝реЛрдВ рдХреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рдВрдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рдм рдХреБрдЫ рд╣реИ, рд▓реЗрдХрд┐рди рджреВрд░реА рдХреЗ рд╕рдВрдХреЗрдд рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЕрджреНрднреБрдд рд╕рдВрдкрддреНрддрд┐ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдЗрд╕ рддрдХ рд╕реАрдорд┐рдд рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдЖрдВрдХрдбрд╝реЗ рдЧрдардмрдВрдзрди рдХрд░рдиреЗ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░рдиреЗ рдХреЗ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдореИрдВ рдЗрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рддрдХрдиреАрдХреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╕рдордЭрд╛рдКрдБрдЧрд╛, рд▓реЗрдХрд┐рди рдЖрдк http://mercury.sexy/hg_sdf рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдХрдИ рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЛ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдпрджрд┐ рдЖрдк рдЕрдиреНрдп рдЙрдкрдпреЛрдЧреА рдПрд╕рдбреАрдПрдл рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рдЬрд╛рдирддреЗ рд╣реИрдВ рддреЛ рдореБрдЭреЗ рд▓рд┐рдЦреЗрдВ)ред

рдЧреЛрд▓рд╛рдИ


рд╣рдо рд╕рдордиреНрд╡рдп рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рд╕реНрдерд┐рддрд┐ рдХреЗ x- рдЕрдХреНрд╖ рдФрд░ y- рдЕрдХреНрд╖ рдХреЗ рд░реВрдк рдореЗрдВ рджреЛ рд╕рдВрдпреЛрдЬрди рдЖрдВрдХрдбрд╝реЛрдВ рдХреА рд╕рддрд╣ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рдордиреНрд╡рдп рдореВрд▓ рдХреА рджреВрд░реА рдХреА рдЧрдгрдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рд╣рдо рдРрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдПрдХ рдмрд╣реБрдд рд╣реА рдЕрдЬреАрдм рдЖрдВрдХрдбрд╝рд╛ рдорд┐рд▓реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдо рдЕрдХреНрд╖ рдХреЛ 0 рд╕реЗ рдиреАрдЪреЗ рдХреЗ рдореВрд▓реНрдпреЛрдВ рддрдХ рд╕реАрдорд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдХреБрдЫ рдРрд╕рд╛ рдорд┐рд▓рддрд╛ рд╣реИ рдЬреЛ рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдХреА рдЖрдВрддрд░рд┐рдХ рджреВрд░реА рдХреЗ рд╕реБрдЧрдо рд╕рдВрдпреБрдЧреНрдо рдХреЗ рд╕рдорд╛рди рд╣реЛрддрд╛ рд╣реИред

 float round_merge(float shape1, float shape2, float radius){ float2 intersectionSpace = float2(shape1, shape2); intersectionSpace = min(intersectionSpace, 0); return length(intersectionSpace); } 


рдпрд╣ рд╕реБрдВрджрд░ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрд╕ рд░реЗрдЦрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рджреВрд░реА 0 рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдСрдкрд░реЗрд╢рди рд╕рд╛рдзрд╛рд░рдг рдпреБрдЧреНрдорди рд╕реЗ рдЕрдзрд┐рдХ рдореВрд▓реНрдпрд╡рд╛рди рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рджреЛ рдЖрдВрдХрдбрд╝реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рд╣рдо рдЙрдиреНрд╣реЗрдВ рдереЛрдбрд╝рд╛ рдмрдврд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрд╕реА рддрд░рд╣ рдЬреИрд╕реЗ рд╣рдордиреЗ рдПрдХ рд╡реГрддреНрдд рдмрдирд╛рдпрд╛, рдПрдХ рдЖрдХреГрддрд┐ рдХреЛ рдмрдбрд╝рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдкрдВрдХреНрддрд┐ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрд╕рдХреА рджреВрд░реА рд╕реЗ рдШрдЯрд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдЪрд┐рдиреНрд╣ рдХреЗ рд╕рд╛рде рджреВрд░реА 0 рд╣реИред

 float radius = max(sin(_Time.y * 5) * 0.5 + 0.4, 0); float combination = round_intersect(squareShape, circleShape, radius); 

 float round_merge(float shape1, float shape2, float radius){ float2 intersectionSpace = float2(shape1 - radius, shape2 - radius); intersectionSpace = min(intersectionSpace, 0); return length(intersectionSpace); } 


рдпрд╣ рдХреЗрд╡рд▓ рдЖрдВрдХрдбрд╝реЗ рдХреЛ рдмрдврд╝рд╛рддрд╛ рд╣реИ рдФрд░ рдЕрдВрджрд░ рд╕реБрдЪрд╛рд░реВ рдмрджрд▓рд╛рд╡ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдЖрдВрдХрдбрд╝реЗ рдмрдврд╝рд╛рдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЪрд┐рдХрдиреА рд╕рдВрдХреНрд░рдордг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд▓рдВрдмрд╛рдИ рдХреА рдЧрдгрдирд╛ рдХреЗ рдмрд╛рдж рд╕рдорд╛рдзрд╛рди рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рдШрдЯрд╛рдирд╛ рд╣реИред рдЕрдзрд┐рдХрд╛рдВрд╢ рднрд╛рдЧ рдкрд╣рд▓реЗ рдЬреИрд╕реЗ рд╣реА рджрд┐рдЦреЗрдВрдЧреЗ, рдХреЗрд╡рд▓ рдЖрдВрдХрдбрд╝реЛрдВ рдХреЗ рдмреАрдЪ рд╕рдВрдХреНрд░рдордг рдХреЛ рдЫреЛрдбрд╝рдХрд░, рдЬреЛ рдХрд┐ рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЦреВрдмрд╕реВрд░рддреА рд╕реЗ рдЪрд┐рдХрдирд╛ рд╣реИред рд╣рдо рдЕрднреА рдХреЗ рд▓рд┐рдП рдЖрдВрдХрдбрд╝реЗ рдХреЗ рдмрд╛рд╣рд░реА рд╣рд┐рд╕реНрд╕реЗ рдХреА рдЕрдирджреЗрдЦреА рдХрд░реЗрдВрдЧреЗред

 float round_merge(float shape1, float shape2, float radius){ float2 intersectionSpace = float2(shape1 - radius, shape2 - radius); intersectionSpace = min(intersectionSpace, 0); return length(intersectionSpace) - radius; } 


рдЕрдВрддрд┐рдо рдЪрд░рдг рдЖрдХреГрддрд┐ рдХреЗ рдмрд╛рд╣рд░реА рднрд╛рдЧ рдХрд╛ рд╕реБрдзрд╛рд░ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрдмрдХрд┐ рдЖрдВрдХрдбрд╝рд╛ рдЕрдВрджрд░ рд╕реЗ рд╣рд░рд╛ рд╣реИ, рдФрд░ рд╣рдо рдЗрд╕ рд░рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдмрд╛рд╣рд░ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВред рдкрд╣рд▓рд╛ рдХрджрдо рдмрд╛рд╣рд░реА рдФрд░ рдЖрдВрддрд░рд┐рдХ рднрд╛рдЧреЛрдВ рдХреЛ рд╕реНрд╡реИрдк рдХрд░рдирд╛ рд╣реИ, рдмрд╕ рдПрдХ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рдЙрдирдХреА рджреВрд░реА рдХреЛ рдЙрд▓рдЯ рдХрд░ред рдлрд┐рд░ рд╣рдо рдЙрд╕ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рддреНрд░рд┐рдЬреНрдпрд╛ рдШрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкрд╣рд▓реЗ рд╣рдо рдЗрд╕реЗ рдШрдЯрд╛рд╡ рд╕реЗ рдЬреЛрдбрд╝рдХрд░ рдмрджрд▓рддреЗ рд╣реИрдВред рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдордиреЗ рд╡реЗрдХреНрдЯрд░ рдХреА рджреВрд░реА рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП, рдЗрд╕рдХреЗ рдЕрдиреБрд╕рд╛рд░, рд╣рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдП рдЧрдП рдЧрдгрд┐рддреАрдп рдСрдкрд░реЗрд╢рди рдХреЛ рдЙрд▓реНрдЯрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдлрд┐рд░ рд╣рдо рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рджреЛрд╕реНрдд рдХреЗ рд╕рд╛рде рдмрджрд▓ рджреЗрдВрдЧреЗ, рдЬреЛ рд╣рдореЗрдВ рдЖрдВрдХрдбрд╝реЗ рдХреЗ рдмрд╛рд╣рд░ рд╕рд╣реА рдорд╛рди рджреЗрдЧрд╛, рд▓реЗрдХрд┐рди рдХрд┐рдирд╛рд░реЛрдВ рдХреЗ рдХрд░реАрдм рдФрд░ рдЖрдВрдХрдбрд╝реЗ рдХреЗ рдЕрдВрджрд░ рдирд╣реАрдВред рдЗрд╕рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдорд╛рди рдФрд░ рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЗ рдмреАрдЪ рдПрдХ рдЕрдзрд┐рдХрддрдо рд▓реЗрддреЗ рд╣реИрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЖрдХреГрддрд┐ рдХреЗ рдмрд╛рд╣рд░ рд╕рд╣реА рдорд╛рдиреЛрдВ рдХрд╛ рдПрдХ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рд╕рд╛рде рд╣рдореЗрдВ рдЙрд╕ рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЗ рдЬреЛрдбрд╝ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдЖрдВрдХрдбрд╝реЗ рдХреЗ рдЕрдВрджрд░ рд╣реИред

 float round_merge(float shape1, float shape2, float radius){ float2 intersectionSpace = float2(shape1 - radius, shape2 - radius); intersectionSpace = min(intersectionSpace, 0); float insideDistance = -length(intersectionSpace); float simpleUnion = merge(shape1, shape2); float outsideDistance = max(simpleUnion, radius); return insideDistance + outsideDistance; } 


рдПрдХ рдЪреМрд░рд╛рд╣рд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рддреНрд░рд┐рдЬреНрдпрд╛ рджреНрд╡рд╛рд░рд╛ рдЖрдВрдХрдбрд╝реЗ рдХрдо рдХрд░реЗрдВ, рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рд╡реЗрдХреНрдЯрд░ рдХреЗ рд╕рднреА рдШрдЯрдХ 0 рд╕реЗ рдЕрдзрд┐рдХ рд╣реИрдВ, рд▓рдВрдмрд╛рдИ рд▓реЗрдВ рдФрд░ рдЗрд╕рдХреЗ рд╕рдВрдХреЗрдд рдХреЛ рди рдмрджрд▓реЗрдВред рдЗрд╕рд▓рд┐рдП рд╣рдо рдЖрдХреГрддрд┐ рдХреЗ рдмрд╛рд╣рд░реА рднрд╛рдЧ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВрдЧреЗред рдлрд┐рд░, рдЖрдВрддрд░рд┐рдХ рднрд╛рдЧ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рд╛рдорд╛рдиреНрдп рдЪреМрд░рд╛рд╣реЗ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рддреНрд░рд┐рдЬреНрдпрд╛ рд╕реЗ рдХрдо рдирд╣реАрдВ рд╣реИред рдлрд┐рд░, рдкрд╣рд▓реЗ рдХреА рддрд░рд╣, рд╣рдо рдЖрдВрддрд░рд┐рдХ рдФрд░ рдмрд╛рд╣рд░реА рдореВрд▓реНрдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред

 float round_intersect(float shape1, float shape2, float radius){ float2 intersectionSpace = float2(shape1 + radius, shape2 + radius); intersectionSpace = max(intersectionSpace, 0); float outsideDistance = length(intersectionSpace); float simpleIntersection = intersect(shape1, shape2); float insideDistance = min(simpleIntersection, -radius); return outsideDistance + insideDistance; } 


рдФрд░ рдПрдХ рдЕрдВрддрд┐рдо рдмрд┐рдВрджреБ рдХреЗ рд░реВрдк рдореЗрдВ, рдШрдЯрд╛рд╡ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЖрдзрд╛рд░ рдЖрдХреГрддрд┐ рдФрд░ рд╕рдм рдХреБрдЫ рдХреЗ рдмреАрдЪ рдЪреМрд░рд╛рд╣реЗ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдЙрд╕ рдЖрдВрдХрдбрд╝реЗ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЬрд┐рд╕реЗ рд╣рдо рдШрдЯрд╛ рд░рд╣реЗ рд╣реИрдВред

 float round_subtract(float base, float subtraction, float radius){ round_intersect(base, -subtraction, radius); } 


рдпрд╣рд╛рдВ, рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдШрдЯрд╛рддреЗ рд╕рдордп, рдЖрдк рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рдЗрд╕ рдзрд╛рд░рдгрд╛ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддреЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдХреЛ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдзрд┐рдХрд╛рдВрд╢ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП, рджреВрд░реА рдХреЗ рдХреНрд╖реЗрддреНрд░ рдЕрднреА рднреА рдХрд╛рдлреА рдЕрдЪреНрдЫреЗ рд╣реИрдВред

рдЭреБрдХрдирд╛


рд╣рдо рдЗрд╕реЗ рдПрдХ рдЪреИрдВрдмрд░ рдХреА рддрд░рд╣ рдХреЛрдг рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдХреНрд░рдордг рдХрд╛ рднреА рдЙрд▓реНрд▓реЗрдЦ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдкреНрд░рднрд╛рд╡ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд╣рд▓реЗ рдореМрдЬреВрджрд╛ рджреЛ рдХреЛ рдЬреЛрдбрд╝рдХрд░ рдПрдХ рдирдпрд╛ рдЖрдХрд╛рд░ рдмрдирд╛рддреЗ рд╣реИрдВред рдпрджрд┐ рд╣рдо рдлрд┐рд░ рд╕реЗ рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВ рдХрд┐ рдЬрд┐рд╕ рдмрд┐рдВрджреБ рдкрд░ рджреЛ рдЖрдВрдХрдбрд╝реЗ рдорд┐рд▓рддреЗ рд╣реИрдВ рд╡рд╣ рдСрд░реНрдереЛрдЧреЛрдирд▓ рд╣реИ, рддреЛ рдпрд╣ рдСрдкрд░реЗрд╢рди рд╣рдореЗрдВ рджреЛ рд╕рддрд╣реЛрдВ рдХреЗ рдорд┐рд▓рдиреЗ рдХреЗ рдмрд┐рдВрджреБ рд╕реЗ рдЧреБрдЬрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рд╡рд┐рдХрд░реНрдг рд░реЗрдЦрд╛ рджреЗрдЧрд╛ред


рдЪреВрдВрдХрд┐ рд╣рдордиреЗ рдмрд╕ рджреЛ рдШрдЯрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рд╣реИ, рдЗрд╕ рдирдИ рд░реЗрдЦрд╛ рдХреЗ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рджреВрд░реА рдореЗрдВ рдЧрд▓рдд рдкреИрдорд╛рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдЗрд╕реЗ рдПрдХ рдЗрдХрд╛рдИ рд╡рд░реНрдЧ рдХреЗ рд╡рд┐рдХрд░реНрдг рджреНрд╡рд╛рд░рд╛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдХреЗ рдареАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рдд, 2 рдХреА рдЬрдбрд╝ рд╕реЗ 2 рдХрд╛ рд╡рд░реНрдЧрдореВрд▓ рд╕рдорд╛рди рд╣реИред 0.5 рдХреЗ рд╡рд░реНрдЧрдореВрд▓ рд╕реЗ рдЧреБрдгрд╛ рдХрд░рдирд╛, рдФрд░ рд╣рдо рдмрд╕ рдХреЛрдб рдХреЛ рдЗрд╕ рдорд╛рди рдХреЛ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╣рд░ рдмрд╛рд░ рдЙрд╕реА рд░реВрдЯ рдХреА рдЧрдгрдирд╛ рди рдХрд░реЗрдВред

рдЕрдм рдЬрдмрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЖрдХрд╛рд░ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рд╡рд╛рдВрдЫрд┐рдд рдмреЗрд╡реЗрд▓ рдХрд╛ рдЖрдХрд╛рд░ рд╣реИ, рд╣рдо рдЗрд╕реЗ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рдмреЗрд╡рд▓ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдЖрдВрдХрдбрд╝рд╛ рдХреА рд╕реАрдорд╛рдУрдВ рд╕реЗ рдкрд░реЗ рд╣реЛред рдкрд╣рд▓реЗ рдХреА рддрд░рд╣ рд╣реА, рд╣рдо рдЙрд╕ рдореВрд▓реНрдп рдХреЛ рдШрдЯрд╛рддреЗ рд╣реИрдВ рдЬреЛ рд╣рдореЗрдВ рдЖрдВрдХрдбрд╝рд╛ рдмрдврд╝рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдлрд┐рд░ рд╣рдо рд╕рд╛рдорд╛рдиреНрдп рдорд░реНрдЬ рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд╕рд╛рде рдмреЗрд╡рд▓ рдЖрдХрд╛рд░ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдмреЗрд╡реЗрд▓ рд╕рдВрдХреНрд░рдордг рд╣реЛрддрд╛ рд╣реИред

 float champferSize = sin(_Time.y * 5) * 0.3 + 0.3; float combination = champfer_merge(circleShape, squareShape, champferSize); 

 float champfer_merge(float shape1, float shape2, float champferSize){ const float SQRT_05 = 0.70710678118; float simpleMerge = merge(shape1, shape2); float champfer = (shape1 + shape2) * SQRT_05; champfer = champfer - champferSize; return merge(simpleMerge, champfer); } 


рдПрдХ рдкрд╛рд░ рдмреЗрд╡рд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо, рдкрд╣рд▓реЗ рдХреА рддрд░рд╣, рджреЛ рдЖрдВрдХрдбрд╝реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рд╣рдо рдмреЗрд╡рд▓ рдХреЗ рдореВрд▓реНрдп рдХреЛ рдЬреЛрдбрд╝рдХрд░ рдЖрдВрдХрдбрд╝рд╛ рдХреЛ рдХрдо рдХрд░ рджреЗрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рдкрд╛рд░ рдХреА рдЧрдИ рдЖрдХреГрддрд┐ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдЪреНрдЫреЗрдж рдХрд░рддреЗ рд╣реИрдВред

 float champfer_intersect(float shape1, float shape2, float champferSize){ const float SQRT_05 = 0.70710678118; float simpleIntersect = intersect(shape1, shape2); float champfer = (shape1 + shape2) * SQRT_05; champfer = champfer + champferSize; return intersect(simpleIntersect, champfer); } 


рдФрд░ рдкрд┐рдЫрд▓реЗ рдШрдЯрд╛рд╡ рдХреЗ рд╕рдорд╛рди, рд╣рдо рдпрд╣рд╛рдВ рджреВрд╕рд░реЗ рдЙрд▓реНрдЯреЗ рдЖрдХреГрддрд┐ рдХреЗ рд╕рд╛рде рдЪреМрд░рд╛рд╣реЗ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

 float champfer_subtract(float base, float subtraction, float champferSize){ return champfer_intersect(base, -subtraction, champferSize); } 


рдЧреЛрд▓ рдЪреМрд░рд╛рд╣рд╛


рдЕрдм рддрдХ, рд╣рдордиреЗ рдХреЗрд╡рд▓ рдмреВрд▓рд┐рдпрди рдСрдкрд░реЗрдЯрд░реЛрдВ (рдкреНрд░рдХреНрд╖реЗрдк рдХреЗ рдЕрд▓рд╛рд╡рд╛) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рд╕реЗ рдЖрдХреГрддрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрди рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдирдП рдЧреЛрд▓ рдЖрдХрд╛рд░ рдмрдирд╛рдХрд░ рдЬрд╣рд╛рдВ рджреЛ рдЖрдХреГрддрд┐рдпреЛрдВ рдХреА рд╕реАрдорд╛рдПрдВ рдУрд╡рд░рд▓реИрдк рд╣реЛрддреА рд╣реИрдВред

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдмрд┐рдВрджреБ рдХреЗ x- рдЕрдХреНрд╖ рдФрд░ y- рдЕрдХреНрд╖ рдХреЗ рд░реВрдк рдореЗрдВ рджреЛ рдЖрдВрдХрдбрд╝реЛрдВ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рддрдм рд╣рдо рдореВрд▓ рдореЗрдВ рдЗрд╕ рдмрд┐рдВрджреБ рдХреА рджреВрд░реА рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВред рдЬрд╣рд╛рдБ рджреЛ рдЖрдХреГрддрд┐рдпреЛрдВ рдХреА рд╕реАрдорд╛рдПрдБ рдУрд╡рд░рд▓реИрдк рд╣реЛрддреА рд╣реИрдВ, рджреЛрдиреЛрдВ рдЖрдХреГрддрд┐рдпреЛрдВ рдХреА рджреВрд░реА 0 рд╣реЛрдЧреА, рдЬреЛ рд╣рдореЗрдВ рд╣рдорд╛рд░реЗ рдХрд╛рд▓реНрдкрдирд┐рдХ рд╕рдордиреНрд╡рдп рдкреНрд░рдгрд╛рд▓реА рдХреА рдЙрддреНрдкрддреНрддрд┐ рдХреЗ рдмрд┐рдВрджреБ рд╕реЗ 0 рдХреА рджреВрд░реА рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИред рдлрд┐рд░, рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрддреНрдкрддреНрддрд┐ рдХреА рджреВрд░реА рд╣реИ, рддреЛ рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рдЙрд╕реА рддрд░рд╣ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ рдХрд┐ рд╕рд░реНрдХрд▓ рдХреЗ рд▓рд┐рдП рдФрд░ рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЛ рдШрдЯрд╛рддреЗ рд╣реИрдВред

 float round_border(float shape1, float shape2, float radius){ float2 position = float2(shape1, shape2); float distanceFromBorderIntersection = length(position); return distanceFromBorderIntersection - radius; } 


рдмреЙрд░реНрдбрд░ рдиреЙрдЪ


рдЖрдЦрд┐рд░реА рдЪреАрдЬ рдЬреЛ рдореИрдВ рд╕рдордЭрд╛рдКрдВрдЧрд╛ рд╡рд╣ рд╣реИ рдПрдХ рд╕реАрдорд╛ рдореЗрдВ рдПрдХ рдЖрдХрд╛рд░ рдореЗрдВ рджреВрд╕рд░реЗ рдЖрдХрд╛рд░ рдХреА рд╕реАрдорд╛ рдмрдирд╛рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ред

рд╣рдо рд╕рд░реНрдХрд▓ рдХреА рд╕реАрдорд╛ рдХреЗ рдЖрдХрд╛рд░ рдХреА рдЧрдгрдирд╛ рдХрд░рдХреЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдкрд╣рд▓реЗ рдЖрдВрдХрдбрд╝реЗ рдХреА рджреВрд░реА рдХрд╛ рдкреВрд░реНрдг рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдЖрдВрддрд░рд┐рдХ рдФрд░ рдмрд╛рд╣рд░реА рджреЛрдиреЛрдВ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдЖрдХреГрддрд┐ рдХрд╛ рдЖрдВрддрд░рд┐рдХ рднрд╛рдЧ рдорд╛рдирд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рд╕реАрдорд╛ рдХрд╛ рдЕрднреА рднреА рдореВрд▓реНрдп рд╣реИ 0. рдпрджрд┐ рд╣рдо рдкрд╛рдпрджрд╛рди рдХреА рдЪреМрдбрд╝рд╛рдИ рдХреЛ рдШрдЯрд╛рдХрд░ рдЗрд╕ рдЖрдВрдХрдбрд╝реЗ рдХреЛ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдкрд┐рдЫрд▓реЗ рдЖрдВрдХрдбрд╝реЗ рдХреА рд╕реАрдорд╛ рдХреЗ рд╕рд╛рде рдЖрдВрдХрдбрд╝рд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ ред

 float depth = max(sin(_Time.y * 5) * 0.5 + 0.4, 0); float combination = groove_border(squareShape, circleShape, .3, depth); 

 float groove_border(float base, float groove, float width, float depth){ float circleBorder = abs(groove) - width; return circleBorder; } 


рдЕрдм рд╣рдореЗрдВ рдХреЗрд╡рд▓ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдореВрд▓реНрдп рд╕реЗ рдЧрд╣рд░рд╛рдИ рддрдХ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрдХрд▓ рдХреА рд╕реАрдорд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕реЗ рдЖрдзрд╛рд░ рдЖрдХреГрддрд┐ рдХреЗ рдПрдХ рдХрдо рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рдШрдЯрд╛рддреЗ рд╣реИрдВред рдЖрдзрд╛рд░ рдЖрдХрд╛рд░ рдореЗрдВ рдХрдореА рдХреА рдорд╛рддреНрд░рд╛ рдкрд╛рдпрджрд╛рди рдХреА рдЧрд╣рд░рд╛рдИ рд╣реИред

 float groove_border(float base, float groove, float width, float depth){ float circleBorder = abs(groove) - width; float grooveShape = subtract(circleBorder, base + depth); return grooveShape; } 


рдЕрдВрддрд┐рдо рдЪрд░рдг рдЖрдзрд╛рд░ рдЖрдХрд╛рд░ рд╕реЗ рдкрд╛рдпрджрд╛рди рдХреЛ рдШрдЯрд╛рдирд╛ рдФрд░ рдкрд░рд┐рдгрд╛рдо рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рд╣реИред

 float groove_border(float base, float groove, float width, float depth){ float circleBorder = abs(groove) - width; float grooveShape = subtract(circleBorder, base + depth); return subtract(base, grooveShape); } 


рд╕реНрд░реЛрдд рдХреЛрдб


рдкреБрд╕реНрддрдХрд╛рд▓рдп



 #ifndef SDF_2D #define SDF_2D //transforms float2 rotate(float2 samplePosition, float rotation){ const float PI = 3.14159; float angle = rotation * PI * 2 * -1; float sine, cosine; sincos(angle, sine, cosine); return float2(cosine * samplePosition.x + sine * samplePosition.y, cosine * samplePosition.y - sine * samplePosition.x); } float2 translate(float2 samplePosition, float2 offset){ //move samplepoint in the opposite direction that we want to move shapes in return samplePosition - offset; } float2 scale(float2 samplePosition, float scale){ return samplePosition / scale; } //combinations ///basic float merge(float shape1, float shape2){ return min(shape1, shape2); } float intersect(float shape1, float shape2){ return max(shape1, shape2); } float subtract(float base, float subtraction){ return intersect(base, -subtraction); } float interpolate(float shape1, float shape2, float amount){ return lerp(shape1, shape2, amount); } /// round float round_merge(float shape1, float shape2, float radius){ float2 intersectionSpace = float2(shape1 - radius, shape2 - radius); intersectionSpace = min(intersectionSpace, 0); float insideDistance = -length(intersectionSpace); float simpleUnion = merge(shape1, shape2); float outsideDistance = max(simpleUnion, radius); return insideDistance + outsideDistance; } float round_intersect(float shape1, float shape2, float radius){ float2 intersectionSpace = float2(shape1 + radius, shape2 + radius); intersectionSpace = max(intersectionSpace, 0); float outsideDistance = length(intersectionSpace); float simpleIntersection = intersect(shape1, shape2); float insideDistance = min(simpleIntersection, -radius); return outsideDistance + insideDistance; } float round_subtract(float base, float subtraction, float radius){ return round_intersect(base, -subtraction, radius); } ///champfer float champfer_merge(float shape1, float shape2, float champferSize){ const float SQRT_05 = 0.70710678118; float simpleMerge = merge(shape1, shape2); float champfer = (shape1 + shape2) * SQRT_05; champfer = champfer - champferSize; return merge(simpleMerge, champfer); } float champfer_intersect(float shape1, float shape2, float champferSize){ const float SQRT_05 = 0.70710678118; float simpleIntersect = intersect(shape1, shape2); float champfer = (shape1 + shape2) * SQRT_05; champfer = champfer + champferSize; return intersect(simpleIntersect, champfer); } float champfer_subtract(float base, float subtraction, float champferSize){ return champfer_intersect(base, -subtraction, champferSize); } /// round border intersection float round_border(float shape1, float shape2, float radius){ float2 position = float2(shape1, shape2); float distanceFromBorderIntersection = length(position); return distanceFromBorderIntersection - radius; } float groove_border(float base, float groove, float width, float depth){ float circleBorder = abs(groove) - width; float grooveShape = subtract(circleBorder, base + depth); return subtract(base, grooveShape); } //shapes float circle(float2 samplePosition, float radius){ //get distance from center and grow it according to radius return length(samplePosition) - radius; } float rectangle(float2 samplePosition, float2 halfSize){ float2 componentWiseEdgeDistance = abs(samplePosition) - halfSize; float outsideDistance = length(max(componentWiseEdgeDistance, 0)); float insideDistance = min(max(componentWiseEdgeDistance.x, componentWiseEdgeDistance.y), 0); return outsideDistance + insideDistance; } #endif 

рдЫрд╛рдпрд╛рджрд╛рд░ рдЖрдзрд╛рд░



 Shader "Tutorial/035_2D_SDF_Combinations/Round"{ Properties{ _InsideColor("Inside Color", Color) = (.5, 0, 0, 1) _OutsideColor("Outside Color", Color) = (0, .5, 0, 1) _LineDistance("Mayor Line Distance", Range(0, 2)) = 1 _LineThickness("Mayor Line Thickness", Range(0, 0.1)) = 0.05 [IntRange]_SubLines("Lines between major lines", Range(1, 10)) = 4 _SubLineThickness("Thickness of inbetween lines", Range(0, 0.05)) = 0.01 } SubShader{ //the material is completely non-transparent and is rendered at the same time as the other opaque geometry Tags{ "RenderType"="Opaque" "Queue"="Geometry"} Pass{ CGPROGRAM #include "UnityCG.cginc" #include "2D_SDF.cginc" #pragma vertex vert #pragma fragment frag struct appdata{ float4 vertex : POSITION; }; struct v2f{ float4 position : SV_POSITION; float4 worldPos : TEXCOORD0; }; v2f vert(appdata v){ v2f o; //calculate the position in clip space to render the object o.position = UnityObjectToClipPos(v.vertex); //calculate world position of vertex o.worldPos = mul(unity_ObjectToWorld, v.vertex); return o; } float scene(float2 position) { const float PI = 3.14159; float2 squarePosition = position; squarePosition = translate(squarePosition, float2(1, 0)); squarePosition = rotate(squarePosition, .125); float squareShape = rectangle(squarePosition, float2(2, 2)); float2 circlePosition = position; circlePosition = translate(circlePosition, float2(-1.5, 0)); float circleShape = circle(circlePosition, 2.5); float combination = /* combination calculation here */; return combination; } float4 _InsideColor; float4 _OutsideColor; float _LineDistance; float _LineThickness; float _SubLines; float _SubLineThickness; fixed4 frag(v2f i) : SV_TARGET{ float dist = scene(i.worldPos.xz); fixed4 col = lerp(_InsideColor, _OutsideColor, step(0, dist)); float distanceChange = fwidth(dist) * 0.5; float majorLineDistance = abs(frac(dist / _LineDistance + 0.5) - 0.5) * _LineDistance; float majorLines = smoothstep(_LineThickness - distanceChange, _LineThickness + distanceChange, majorLineDistance); float distanceBetweenSubLines = _LineDistance / _SubLines; float subLineDistance = abs(frac(dist / distanceBetweenSubLines + 0.5) - 0.5) * distanceBetweenSubLines; float subLines = smoothstep(_SubLineThickness - distanceChange, _SubLineThickness + distanceChange, subLineDistance); return col * majorLines * subLines; } ENDCG } } FallBack "Standard" //fallback adds a shadow pass so we get shadows on other objects } 

Source: https://habr.com/ru/post/hi438954/


All Articles