Search Unity

Official Vector Graphics Preview Package

Discussion in 'UI Toolkit' started by rustum, May 4, 2018.

  1. AbgaryanFX

    AbgaryanFX

    Joined:
    Jan 9, 2010
    Posts:
    167
    why there is no news on this package ?
     
  2. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Thanks for reporting this. I'm a bit perplexed by this since we do support the image tag. We'll contact you to better understand how the SVG file was constructed.
     
  3. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    The package is still in its preview phase. We will make some more adjustments following user feedback before making an official announcement.
     
  4. r-pedra

    r-pedra

    Joined:
    Dec 4, 2015
    Posts:
    104
    Hey, I'm using Unity 2018.1.3f1 and the package is 1.0.5-experimental. Whenever I try to import the tiger example I'm getting this error:
    Can you help?
     
  5. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Can you try with version 1.0.0-preview.7 instead? If that doesn't help we'll contact you for more details.
     
  6. foolmoron

    foolmoron

    Joined:
    Jun 22, 2013
    Posts:
    41
    Thanks, I can send you the SVG if you want to try it directly. I think it also has an issue where there's some transparency that isn't working (while other transparency IS working).
     
  7. foolmoron

    foolmoron

    Joined:
    Jun 22, 2013
    Posts:
    41
    Also it seems like the Color field of the SpriteRenderer doesn't work for SVG imported sprites (with either the UnlitVector material or the Sprites-Default). I added an extra script that sets "_Color" on the material and that works fine with both materials though. I'm guessing it has something to do with "_RendererColor".
     
    TheValar likes this.
  8. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    This is probably a side-effect of the SVG sprites already making use of the color channel of the vertices. For that reason, I would expect the _RendererColor to work when instancing is enabled. So it may be worth trying a new material with instancing enabled to see if that helps.
     
  9. r-pedra

    r-pedra

    Joined:
    Dec 4, 2015
    Posts:
    104
    I'm still getting these errors:
    EDIT: Tried with 2018.2.0b6 , same error, still with the tiger example
     
    Last edited: Jun 6, 2018
  10. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    I am getting same SVGFormatException error as @r-pedra with 1.0.0-preview.7 in Unity 2018.2.0b7 and 2018.1.1f1.
     
  11. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789
    Just discovered this, sounds like an awesome addition for UI stuff we have planned (when becomes available for use in Canvas/UI) Great work!

    Can we modify the mesh like any other normal mesh at runtime?
     
    WhiteGfx likes this.
  12. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    This has been fixed recently, you can try with 1.0.0-preview.13, thanks!
     
  13. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Yes. The imported sprite is a regular sprite and you could modify the mesh using the Sprite.OverrideGeometry() method. Alternatively, you can also fill a Mesh object with tessellated geometry. We provide the
    VectorUtils.FillMesh() method for that matter (the Spline.cs example in the sample project does that).
     
  14. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    Yes, the version 1.0.0-preview.13 is working without that error, thank you @mcoted3d !
     
  15. Ferazel

    Ferazel

    Joined:
    Apr 18, 2010
    Posts:
    517
    I'm looking forward to being able to use this package in UI and other situations. In particular I'm really looking forward to the ability to produce quality anti-aliased rasterized versions of the images. Ideally, the images could then be procedurally atlased on the client rather than rely on hard atlas scales. The dream of a resolution independent UI.
     
    Last edited: Jun 14, 2018
  16. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    I must say that so far it works really well, sharp and clear sprites at every resolution. Can we expect possibility to colorize these vector sprites? At the moment changing sprite renderer's color property seems doing nothing.
     
  17. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Yes, this is a known issue. This is caused by the renderer's color property trying to make use of the vertex color channel, which is already used by the SVG sprite.

    A workaround for this is to create a new material for the vector sprite. Set the shader to "Unlit/Vector" or "Unlit/VectorGradient" (if you need textures/gradients) and check the "Enable GPU Instancing" checkbox on the material. By enabling GPU instancing, the color will be passed as an "instanced property" and should have an effect on the vector sprite.
     
  18. atmuc

    atmuc

    Joined:
    Feb 28, 2011
    Posts:
    1,166
    Can I change stroke width of imported SVG?
     
  19. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Once and SVG is imported, the vector shapes are "baked" into the resulting sprite as a triangulated mesh. For that reason, you won't be able to dynamically change the stroke width of an imported SVG.

    However, you can import the SVG file using the SVGParser.ImportSVG() method and modify the resulting Scene object, including the stroke width. You can then tessellate and generate a sprite from that modified Scene afterward. The SVGRuntimeLoad.cs example in the samples project does something similar.

    Note that the SVG parsing/tessellation process is expensive, so use it carefully :) Hope this helps!
     
    khaled24 and AbgaryanFX like this.
  20. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    649
    Wow. I was just lamenting with our artist earlier today that the one thing we felt was still really lacking in our transition from flash -> Unity was the ability to use vector graphics. We do a lot of first person point-and-click adventure games, and our character art has really degraded because of the switch from svg to texture. We have severe file size restraints with our clients, so we can't use super high-res art everywhere, not to mention there are so many different monitor resolutions for us, a single compression size just doesn't look good for every use case.

    I can't speak for anyone else, but this is probably the single most impactful addition to Unity for our shop in a long, long time, and I didn't even know it was coming. Could not be happier to hear about this!! :)

    PS: Please tell me that this will work on WebGL/iOS/Desktop. WebGL is our main target, but the others are required as well.
     
    Thorlar, mcoted3d and nickeron like this.
  21. TheValar

    TheValar

    Joined:
    Nov 12, 2012
    Posts:
    760
    YES! This is something I have been wanting for a long time! Very excited!

    Tried it out a bit and noticed that color tinting doesn't seem to work in the inspector (I think someone already reported that above)

    I'm curious if there will be tools to help create optimized svgs since when you are using your art tool of choice you won't know anything about vert count and overdraw until you actually import into unity. Having in-engine vector editing tools where the mesh gets generated in real time would be pretty neat!

    Speaking of overdraw:
    1: Currently it looks like everything is rendered transparently, will you be providing opaque shaders?
    2: would be very cool if the mesh generator could account for certain cases where transparency is used. For example the artist may have an opaque brown square with a same sized semi-transparent black square over top of it to easily create a darker color, At the end of the day this could be baked down to an opaque piece of geometry

    Anyway sorry for the stream of consciousness. Yay SVGs!
     
    mcoted3d likes this.
  22. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    We're glad to hear that! :)

    Yes, we do plan to support every desktop/mobile platforms and WebGL.
     
  23. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
  24. jeffsarge

    jeffsarge

    Joined:
    Jan 3, 2014
    Posts:
    32
    Can the Unlit Sprite Shader be switched to Lit so they can take advantage of lighting?
     
  25. MythrilMan51

    MythrilMan51

    Joined:
    Apr 24, 2017
    Posts:
    146
    How do I import my SVG's?
     
  26. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    I would think this should be relatively easy to achieve. The Unlit/Vector shader basically only output the color associated to the vertices, so doing a custom lit shader that takes that color as the albedo factor should be simple.
     
  27. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    649
    What is the performance like? Will it be roughly the same as a regular sprite, or much worse? Also, I did notice that the example showed anti-aliasing needed to be turned on. Is there any way around that? Currently, we don't need that turned on for our 2d games, since it doesn't really make a difference, and AA on webgl is a huge performance hit for our target audience. Our stuff needs to run on _very_ low spec machines, so requiring AA just to use the svg graphics is something that could block us from being able to use this.
     
    Edan-Smith likes this.
  28. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Performance for colored SVG sprites should be very similar to regular sprites. However, textured/gradient sprites are more expensive to render as they required a couple of additional texture taps and more per-fragment processing. Highly tessellated sprites may cause some performance issues as well.

    You are correct, we do rely on the multi-sample antialiasing of Unity (MSAA). This usually performs quite well, but it certainly does require more memory. There are other anti-aliasing techniques out there that we could use, but none of them are free (either in computational or memory usage), and all have pros and cons. We opted for MSAA essentially because of its performance and high-quality results.

    You should see if the cost of MSAA it too high on your low-spec devices. Sometimes, even a 2x anti-aliasing value goes a long way. If the cost is still too high, you have other options. Some user decided to render the SVG sprites to and texture (with multi-sampling turned on), and then use the resulting anti-aliased texture as normal sprites. This gives the high-quality anti-aliased results and high performance, but you lose the "infinite" resolution of SVG sprites.

    I hope this helps :)
     
  29. MythrilMan51

    MythrilMan51

    Joined:
    Apr 24, 2017
    Posts:
    146
    Never mind, by the way... Found out it's done by dragging.
     
    mcoted3d likes this.
  30. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    Thank you @mcoted3d , it works.

    BTW, is there a simple way how to use these SVG assets with a new ECS? As far as I know there is just a MeshInstanceRenderer, so I probably need to create a mesh from this SVG somehow and pass it to the MeshInstanceRenderer?
     
  31. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    This has very good chances to work as far as I can tell, but I never tried it personally. We have a utility method to fill a mesh with all the required attributes: VectorUtils.FillMesh(). So you could use that to create the mesh to plug into the MeshInstancedRenderer.
     
  32. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    Ok, thank you, I will try it out. There is so many new things in Unity right now, it is hard to resist the temptation to implement them all :)
     
  33. chiefartificer

    chiefartificer

    Joined:
    Jun 13, 2018
    Posts:
    5
  34. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    My attempt to combine ECS and SVG so far looks like this:
    Code (CSharp):
    1. private void CreateHeroEntity()
    2.     {
    3.         var heroArchetype = entityManager.CreateArchetype(
    4.             typeof(Position2D),
    5.             typeof(Heading2D),
    6.             typeof(Rotation),
    7.             typeof(TransformMatrix));
    8.  
    9.         Entity hero = entityManager.CreateEntity(heroArchetype);
    10.  
    11.         entityManager.SetComponentData(hero, new Position2D { Value = new float2(0.0f, 0.0f) });
    12.         entityManager.SetComponentData(hero, new Heading2D { Value = new float2(0.0f, 1.0f) });
    13.         entityManager.SetComponentData(hero, new Rotation { });
    14.      
    15.         string path = "Assets/_Project/Objects/Coins/Coin.svg";
    16.  
    17.         SVGParser.SceneInfo sceneInfo;
    18.  
    19.         using (StreamReader reader = new StreamReader(path))
    20.         {
    21.             sceneInfo = SVGParser.ImportSVG(reader);
    22.         }
    23.  
    24.         var tessellationOptions = new VectorUtils.TessellationOptions()
    25.         {
    26.             StepDistance = 10f,
    27.             SamplingStepSize = 100f,
    28.             MaxCordDeviation = 1f,
    29.             MaxTanAngleDeviation = 5f
    30.         };
    31.  
    32.         var tessellatedScene = VectorUtils.TessellateScene(sceneInfo.Scene, tessellationOptions);
    33.      
    34.         var material = new Material(Shader.Find("Unlit/Vector"))
    35.         {
    36.             enableInstancing = true
    37.         };
    38.  
    39.         var mesh = new Mesh();
    40.  
    41.         VectorUtils.FillMesh(mesh, tessellatedScene, 100f);
    42.  
    43.         var meshInstanceRenderer = new MeshInstanceRenderer
    44.         {
    45.             mesh = mesh,
    46.             material = material
    47.         };
    48.  
    49.         entityManager.AddSharedComponentData(hero, meshInstanceRenderer);
    50.     }
    It seems like mesh is created ok (all the tris, vertices and colors), entity is created ok, it is picked up by MeshInstanceRendererSystem, no erros in console... But it is not working, the mesh is not visible on the screen. Am I missing something? Maybe something with the rotation?

    EDIT: When I am trying to visualise the mesh with old good combo MeshFilter/MeshRenderer I am getting warning

    Instancing: Use SpriteColor or SpriteFlip for renderers that are not sprite renderers. Values are undefined.


    Is it even possible to render the SVG mesh with MeshRenderer/MeshInstanceRenderer?
     
    Last edited: Jun 28, 2018
  35. thewhitefox

    thewhitefox

    Joined:
    Apr 21, 2014
    Posts:
    3
    Importing an SVG with a fill:rgb(x,y,z) style appears to break the SVG parser. This was tested in 1.0.0-preview.13.
    For instance, this SVG imports properly:
    But this SVG throws an error stack on ParseFill:
    Error Stack:
     
  36. AlexeyB2016

    AlexeyB2016

    Joined:
    Dec 7, 2016
    Posts:
    8
    SVG Importer - great news! How about animated SVG? Does it support CSS-animations?
     
  37. AlexeyB2016

    AlexeyB2016

    Joined:
    Dec 7, 2016
    Posts:
    8
    And how will SVG be rendered when compiled under WebGL? Also in the form of a mesh or more native way?
     
  38. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    I think the problem is that the SVG materials are not "GPU Instancing Enabled". Unfortunately, they aren't instancing compatible at this time.

    However, it is worth trying with a new material with the "Sprites/Default" shader. Check the "Enable GPU Instancing" checkbox and see if that works for the MeshInstancedRenderer. Note that this shader won't properly support textured/gradient SVGs.

    If you are still not successful after that, let me know :)
     
  39. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Animated CSS or animated SVG are not supported. We are currently discussing animation workflows for SVG, so it is still too early to be able to give information about animated SVGs at this time.

    They are rendered as a triangulated mesh (e.g., we are not using the browser's native SVG support).
     
  40. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Thanks, we will look into this!
     
  41. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    Thanks for the tip, but unfortunately it is not working. Rendered object is blinking, changing its size, the colors are wrong. The Standard shader must be sufficient for my needs at the moment, it doesn't render colors, but the shape is ok. I will wait until something better will be avaliable in the future.
     
  42. thewhitefox

    thewhitefox

    Joined:
    Apr 21, 2014
    Posts:
    3
    If a definition is declared after the block in which it is used in the SVG file, it will cause a runtime warning and the SVG fails to render. The gradient itself also fails to import to a texture.

    Moving the <defs> block above the tags that reference it fixes this, but this is the default export format for Affinity Designer, which would be nice to support without having to manually rearrange the file. Problematic file format:
    Import warning:
     
  43. thewhitefox

    thewhitefox

    Joined:
    Apr 21, 2014
    Posts:
    3
    As I was tinkering with the SVG importer in an ECS project, I wrote a couple of (basic) shaders to render different types of imported SVGs with GPU instancing. Note that I recommend using the VectorUtils.FillMesh in an editor tool at import time to convert a SVG file to a mesh asset if you're going to use the MeshInstanceData, as creating them at runtime is quite slow. These are only unlit, but maybe someone else will find them useful.

    Opaque, Vertex-Color only:
    Code (csharp):
    1.  
    2. Shader "Unlit/Vertex Color"
    3. {
    4.     Properties
    5.     {
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.     }
    8.     SubShader
    9.     {
    10.         Tags { "RenderType"="Opaque" }
    11.  
    12.         Pass
    13.         {
    14.             CGPROGRAM
    15.             #pragma vertex vert
    16.             #pragma fragment frag
    17.             #pragma multi_compile_instancing
    18.          
    19.             #include "UnityCG.cginc"
    20.  
    21.             struct appdata
    22.             {
    23.                 float4 vertex : POSITION;
    24.                 fixed4 color : COLOR;
    25.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    26.             };
    27.  
    28.             struct v2f
    29.             {
    30.                 fixed4 color : COLOR;
    31.                 float4 vertex : SV_POSITION;
    32.             };
    33.  
    34.             uniform fixed4 _Color;
    35.  
    36.             v2f vert (appdata v)
    37.             {
    38.                 v2f o;
    39.  
    40.                 UNITY_SETUP_INSTANCE_ID (v);
    41.  
    42.                 o.vertex = UnityObjectToClipPos(v.vertex);
    43.  
    44.                 #ifdef UNITY_COLORSPACE_GAMMA
    45.                 fixed4 color = v.color;
    46.                 #else
    47.                 fixed4 color = fixed4(GammaToLinearSpace(v.color.rgb), v.color.a);
    48.                 #endif
    49.                 o.color = color * _Color;
    50.                 return o;
    51.             }
    52.          
    53.             fixed4 frag (v2f i) : SV_Target
    54.             {
    55.                 return i.color;
    56.             }
    57.             ENDCG
    58.         }
    59.     }
    60. }
    61.  
    Transparent, supports gradients:
    Code (csharp):
    1.  
    2. Shader "Unlit/Vertex Gradient"
    3. {
    4.     Properties
    5.     {
    6.         _MainTex ("Texture", 2D) = "white" {}
    7.         _Color ("Tint", Color) = (1,1,1,1)
    8.     }
    9.     SubShader
    10.     {
    11.         Tags
    12.         {
    13.             "RenderType" = "Transparent"
    14.             "Queue" = "Transparent"
    15.             "IgnoreProjector" = "True"
    16.             "PreviewType" = "Plane"
    17.         }
    18.  
    19.         Cull Off
    20.         Lighting Off
    21.         ZWrite Off
    22.         Blend SrcAlpha OneMinusSrcAlpha
    23.  
    24.         Pass
    25.         {
    26.             CGPROGRAM
    27.             #pragma vertex vert
    28.             #pragma fragment frag
    29.             #pragma multi_compile_instancing
    30.  
    31.             #include "UnityCG.cginc"
    32.  
    33.             struct appdata
    34.             {
    35.                 float4 vertex : POSITION;
    36.                 fixed4 color : COLOR;
    37.                 float2 uv : TEXCOORD0;
    38.                 float2 settingIndex : TEXCOORD2;
    39.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    40.             };
    41.  
    42.             struct v2f
    43.             {
    44.                 fixed4 color : COLOR;
    45.                 float2 uv : TEXCOORD0; // uv.z is used for setting index
    46.                 float2 settingIndex : TEXCOORD2;
    47.                 float4 vertex : SV_POSITION;
    48.             };
    49.  
    50.             sampler2D _MainTex;
    51.             float4 _MainTex_ST;
    52.             float4 _MainTex_TexelSize;
    53.             fixed4 _Color;
    54.          
    55.             v2f vert (appdata v)
    56.             {
    57.                 v2f o;
    58.                 UNITY_SETUP_INSTANCE_ID (v);
    59.                 o.vertex = UnityObjectToClipPos(v.vertex);
    60.  
    61.                 #ifdef UNITY_COLORSPACE_GAMMA
    62.                 fixed4 col = v.color;
    63.                 #else
    64.                 fixed4 col = fixed4(GammaToLinearSpace(v.color.rgb), v.color.a);
    65.                 #endif
    66.                 o.color = col * _Color;
    67.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    68.                 o.settingIndex = v.settingIndex;
    69.                 return o;
    70.             }
    71.  
    72.             float2 unpackFloat2(fixed4 c)
    73.             {
    74.                 return float2(c.r*255 + c.g, c.b*255 + c.a);
    75.             }
    76.  
    77.             float2 rayUnitCircleFirstHit(float2 rayStart, float2 rayDir)
    78.             {
    79.                 float tca = dot(-rayStart, rayDir);
    80.                 float d2 = dot(rayStart, rayStart) - tca * tca;
    81.                 float thc = sqrt(1.0f - d2);
    82.                 float t0 = tca - thc;
    83.                 float t1 = tca + thc;
    84.                 float t = min(t0, t1);
    85.                 if (t < 0.0f)
    86.                     t = max(t0, t1);
    87.                 return rayStart + rayDir * t;
    88.             }
    89.  
    90.             float radialAddress(float2 uv, float2 focus)
    91.             {
    92.                 uv = (uv - float2(0.5f, 0.5f)) * 2.0f;
    93.                 float2 pointOnPerimeter = rayUnitCircleFirstHit(focus, normalize(uv - focus));
    94.                 float2 diff = pointOnPerimeter - focus;
    95.                 if (abs(diff.x) > 0.0001f)
    96.                     return (uv.x - focus.x) / diff.x;
    97.                 if (abs(diff.y) > 0.0001f)
    98.                     return (uv.y - focus.y) / diff.y;
    99.                 return 0.0f;
    100.             }
    101.  
    102.             fixed4 frag (v2f i) : SV_Target
    103.             {
    104.                 // Gradient settings are stored in 3 consecutive texels:
    105.                 // - texel 0: (float4, 1 byte per float)
    106.                 //    x = gradient type (0 = tex/linear, 1 = radial)
    107.                 //    y = address mode (0 = wrap, 1 = clamp, 2 = mirror)
    108.                 //    z = radialFocus.x
    109.                 //    w = radialFocus.y
    110.                 // - texel 1: (float2, 2 bytes per float) atlas entry position
    111.                 //    xy = pos.x
    112.                 //    zw = pos.y
    113.                 // - texel 2: (float2, 2 bytes per float) atlas entry size
    114.                 //    xy = size.x
    115.                 //    zw = size.y
    116.  
    117.                 int settingBase = ((int)(i.settingIndex.x + 0.5f)) * 3;
    118.                 float2 texelSize = _MainTex_TexelSize.xy;
    119.                 float2 settingUV = float2(settingBase + 0.5f, 0.5f) * texelSize;
    120.  
    121.                 float2 uv = i.uv;
    122.                 fixed4 gradSettings = tex2D(_MainTex, settingUV);
    123.                 if (gradSettings.x > 0.0f)
    124.                 {
    125.                     // Radial texture case
    126.                     float2 focus = (gradSettings.zw - float2(0.5f, 0.5f)) * 2.0f; // bring focus in the (-1,1) range                
    127.                     uv = float2(radialAddress(i.uv, focus), 0.0);
    128.                 }
    129.  
    130.                 int addressing = gradSettings.y * 255;
    131.                 uv.x = (addressing == 0) ? fmod(uv.x,1.0f) : uv.x; // Wrap
    132.                 uv.x = (addressing == 1) ? max(min(uv.x,1.0f), 0.0f) : uv.x; // Clamp
    133.                 float w = fmod(uv.x,2.0f);
    134.                 uv.x = (addressing == 2) ? (w > 1.0f ? 1.0f-fmod(w,1.0f) : w) : uv.x; // Mirror
    135.  
    136.                 // Adjust UV to atlas position
    137.                 float2 nextUV = float2(texelSize.x, 0);
    138.                 float2 pos = (unpackFloat2(tex2D(_MainTex, settingUV+nextUV) * 255) + float2(0.5f, 0.5f)) * texelSize;
    139.                 float2 size = unpackFloat2(tex2D(_MainTex, settingUV+nextUV*2) * 255) * texelSize;
    140.                 uv = uv * size + pos;
    141.  
    142.                 fixed4 texColor = tex2D(_MainTex, uv);
    143.                 #ifndef UNITY_COLORSPACE_GAMMA
    144.                 texColor = fixed4(GammaToLinearSpace(texColor.rgb), texColor.a);
    145.                 #endif
    146.  
    147.                 return texColor * i.color;
    148.             }
    149.             ENDCG
    150.         }
    151.     }
    152. }
    153.  
    EDIT: Here is the Editor Script I use for importing an SVG file to a mesh:
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.IO;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6. using UnityEditor;
    7. using Path = System.IO.Path;
    8. using Unity.VectorGraphics;
    9.  
    10. public static class ConvertSVG
    11. {
    12.     /// <summary>
    13.     /// Converts any and all .svg files selected in the Project to a mesh asset.
    14.     /// The mesh will be placed in a folder parallel to the .svg named 'generated_mesh'
    15.     /// This will overwrite an existing asset with the updated mesh data.
    16.     /// </summary>
    17.     [MenuItem("SVG/Create Mesh")]
    18.     public static void CreateMeshAsset()
    19.     {
    20.         //Get all assets in all selected folders
    21.         Object[] objects = Selection.GetFiltered<Object>(SelectionMode.DeepAssets);
    22.         List<string> assetPaths = new List<string>();
    23.  
    24.         //Filter out selected asset paths to only get '.svg' files
    25.         for (int i = 0; i != objects.Length; ++i)
    26.         {
    27.             string path = AssetDatabase.GetAssetPath(objects[i]);
    28.             if (Path.GetExtension(path).Equals(".svg", System.StringComparison.OrdinalIgnoreCase))
    29.             {
    30.                 assetPaths.Add(path);
    31.             }
    32.         }
    33.         //No SVG files in selection
    34.         if (assetPaths.Count == 0)
    35.         {
    36.             Debug.LogWarning("Found no SVG files in the current selection.");
    37.             return;
    38.         }
    39.  
    40.         for (int i = 0; i != assetPaths.Count; ++i)
    41.         {
    42.             EditorUtility.DisplayProgressBar("Importing SVG...", Path.GetFileNameWithoutExtension(assetPaths[i]), (float)i / assetPaths.Count);
    43.             try
    44.             {
    45.                 //Attempt the import process
    46.                 CreateMeshForSVG(assetPaths[i]);
    47.             }
    48.             catch
    49.             {
    50.                 //Clear the progress bar and save any assets that successfully imported, then throw the exception
    51.                 AssetDatabase.SaveAssets();
    52.                 EditorUtility.ClearProgressBar();
    53.                 throw;
    54.             }
    55.         }
    56.         Debug.LogFormat("Sucessfully imported {0} svg assets!", assetPaths.Count);
    57.         EditorUtility.ClearProgressBar();
    58.         AssetDatabase.SaveAssets();
    59.     }
    60.  
    61.     /// <summary>
    62.     /// Creates a mesh file for the SVG file at <paramref name="path"/>.
    63.     /// If the file already exists, it will be updated with the new mesh data.
    64.     /// </summary>
    65.     /// <param name="path">Path of the SVG file.</param>
    66.     static void CreateMeshForSVG(string path)
    67.     {
    68.         //Output path will be in a 'generated_mesh' folder parallel to the svg asset file.
    69.         var outputPath = Path.GetDirectoryName(path);
    70.         outputPath = Path.Combine(outputPath, "generated_mesh");
    71.         //Create the output directory if it doesn't already exist
    72.         if (!Directory.Exists(outputPath))
    73.         {
    74.             AssetDatabase.CreateFolder(Path.GetDirectoryName(path), "generated_mesh");
    75.         }
    76.         //Final output path of the mesh asset
    77.         outputPath = Path.Combine(outputPath, Path.GetFileNameWithoutExtension(path) + ".asset");
    78.  
    79.         SVGParser.SceneInfo sceneInfo;
    80.         //Read the SVG file from disk
    81.         using (StreamReader reader = new StreamReader(path))
    82.         {
    83.             sceneInfo = SVGParser.ImportSVG(reader, 72, 100);
    84.         }
    85.  
    86.         //Adjust tessellation options as necessary. These are default import settings.
    87.         var tessellationOptions = new VectorUtils.TessellationOptions
    88.         {
    89.             StepDistance = 10f,
    90.             SamplingStepSize = 100f,
    91.             MaxCordDeviation = 1f,
    92.             MaxTanAngleDeviation = 5f
    93.         };
    94.  
    95.         //Check if the file already exists
    96.         bool isNewFile = false;
    97.         Mesh mesh;
    98.         if (File.Exists(outputPath))
    99.         {
    100.             //The file exists, so we'll overwrite the old one instead of creating a new one
    101.             mesh = AssetDatabase.LoadAssetAtPath<Mesh>(outputPath);
    102.         }
    103.         else
    104.         {
    105.             //The file doesn't already exist, so create a new one
    106.             mesh = new Mesh();
    107.             isNewFile = true;
    108.         }
    109.  
    110.         //Tessellate the vector scene into geometry
    111.         var tessellated = VectorUtils.TessellateScene(sceneInfo.Scene, tessellationOptions);
    112.  
    113.         //Generate an atlas texture if necessary (used for gradients and patterns)
    114.         var texAtlas = VectorUtils.GenerateAtlasAndFillUVs(tessellated, 128);
    115.  
    116.         //Populate the mesh data
    117.         VectorUtils.FillMesh(mesh, tessellated, 100f);
    118.  
    119.         //[Optional] - This block of code will center the pivot of the mesh to the center of the vertices
    120.         {
    121.             //[Optional] - This rotation will face the mesh 'toward' the Y axis with Z as forward.
    122.             //Other helpful rotations:
    123.                 //Quaternion.Euler(0f, 0f, 180f) -> "Sprite Import" z-axis default
    124.                 //Quaternion.identity -> "Default Orientation", as-is in svg file
    125.             Quaternion outputRotation = Quaternion.Euler(90f, 180f, 0f);
    126.             mesh.RecalculateBounds();
    127.             Vector3 centerPoint = mesh.bounds.center;
    128.             List<Vector3> verts = new List<Vector3>();
    129.             mesh.GetVertices(verts);
    130.             Matrix4x4 transformMatrix = Matrix4x4.TRS(Vector3.zero, outputRotation, Vector3.one);
    131.  
    132.             for (int i = 0; i != verts.Count; ++i)
    133.             {
    134.                 Vector3 vert = verts[i] - centerPoint;
    135.                 Vector3 newVert = transformMatrix.MultiplyPoint3x4(vert);
    136.                 verts[i] = newVert;
    137.             }
    138.             mesh.SetVertices(verts);
    139.             mesh.RecalculateBounds();
    140.         }
    141.  
    142.         //Creates a new file, since a file didn't already exist
    143.         if (isNewFile)
    144.         {
    145.             Debug.Log("Created asset at path: " + outputPath);
    146.             AssetDatabase.CreateAsset(mesh, outputPath);
    147.         }
    148.         //Updates an existing file, preserving references to other objects
    149.         else
    150.         {
    151.             Debug.Log("Updated asset at path: " + outputPath);
    152.             EditorUtility.SetDirty(mesh);
    153.         }
    154.  
    155.         //After the mesh has been created, create or update the texture atlas file if necessary
    156.         if (texAtlas != null && texAtlas.Texture != null)
    157.         {
    158.             CreateTextureFile(texAtlas.Texture, outputPath);
    159.         }
    160.     }
    161.  
    162.     /// <summary>
    163.     /// Outputs the texture atlas file inside the mesh asset at <paramref name="path"/>
    164.     /// </summary>
    165.     /// <param name="texture">Texture Atlas (generated by GenerateAtlasAndFillUVs.</param>
    166.     /// <param name="path">Path of the output mesh asset (created by the editor script).</param>
    167.     static void CreateTextureFile(Texture2D texture, string path)
    168.     {
    169.         string outputName = Path.GetFileNameWithoutExtension(path) + "Atlas";
    170.         texture.name = outputName;
    171.         var subAssets = AssetDatabase.LoadAllAssetRepresentationsAtPath(path);
    172.         for (int i = 0; i != subAssets.Length; ++i)
    173.         {
    174.             if(subAssets[i].name.Equals(outputName, System.StringComparison.OrdinalIgnoreCase))
    175.             {
    176.                 //Copy the data from the new texture overtop the old, to keep the original references
    177.                 EditorUtility.CopySerialized(texture, subAssets[i]);
    178.                 EditorUtility.SetDirty(subAssets[i]);
    179.                 return;
    180.             }
    181.         }
    182.         //Since this asset didn't already have a texture atlas, create a new one inside it.
    183.         AssetDatabase.AddObjectToAsset(texture, path);
    184.     }
    185. }
    186.  
     
    Last edited: Jul 1, 2018
    Rowlan, simi_, sonofbryce and 2 others like this.
  44. ERENKYI

    ERENKYI

    Joined:
    Jun 1, 2017
    Posts:
    4
    What's the performance difference between this and using an image? Also, will this be a part of Unity when it comes out of beta (if it does), so we can expect asset creators to support 2D SVG assets?
     
  45. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    The performance between an image and a simple colored SVG sprite should be the same (unless you have a highly tessellated SVG sprite, which will affect performances). Textured and gradient SVG sprites are slower to render as they require a few texture taps and more per-fragment processing. What you get in return is potentially "infinite" resolution.

    We plan to keep this as a package. In fact, more and more Unity features are moving to packages as well. It is not clear to me how asset creators will handle this situation though, but I'm pretty sure the package manager team will have something to accommodate this. I would think that asset store packages will be able to explicitly impose the required packages for their assets. Or maybe asset store packages will be transitioned to the package manager as well (and therefore, inherit the package dependency feature "for free"). Only time will tell :)
     
    ERENKYI likes this.
  46. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Any chance of getting a name change for Unity.VectorGraphics.Scene? Or just get rid of it - does it serve any purpose other than holding the Root?

    EDIT: In fact it seems like the runtime API names just need a going over in general (maybe that's still planned?) I'm not sure what a Unity.VectorGraphics.Rectangle is, but it doesn't seem to be a rectangle.
     
    Last edited: Jul 5, 2018
  47. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    As long as I'm complaining about stuff... ;)

    Having two Bezier classes seems inelegant, can't some of the methods just take a closing point, instead of having separate classes with and without the fourth vertex?

    EDIT: I'm using a Bezier vertex struct that combines the vertex with a "enter" and "exit" control point, rather than the two following control points. It means you always need at least two, but otherwise it's a little tidier IMO.
     
    Last edited: Jul 5, 2018
  48. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    That's a good question, I'm not sure how we ended up with this basically empty class. We may have future plans for it though. I'll have a look with the team.

    It represents a rectangle with optionally rounded corners. For example:

    Code (CSharp):
    1.  
    2. var rect = new Rectangle() {
    3.     Size = new Vector2(3, 2),
    4.     Fill = new SolidFill() { Color = Color.red }
    5. };
    6.  
    7. var scene = new Scene() {
    8.     Root = new SceneNode() { Drawables = new List<IDrawable> { rect } }
    9. };
    10.  
    11. var geoms = VectorUtils.TessellateScene(scene, options);
    12. // "geoms" now has a tessellated red rectangle
    13.  
    I agree that having two Bezier structs is not desirable. The BezierSegment struct should be used in most situations since it's the classic Bezier definition that we all know and understand. We introduced the BezierPathSegment to guarantee the continuity of multiple chained segments. This was very helpful to simplify the "path distance forward iterator" that takes care of measuring the segments lengths and taking care of dashed segments and everything else.

    Thank you for your feedback, it is very much appreciated! :)
     
  49. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Aha! I was confused by the fact VectorUtils.MakeCircle() and VectorUtils.MakeEllipse() were returning "Rectangles". :confused:

    Is that more efficient than just using the Shape class, and adding MakeRectangle() and MakeRoundRect() to VectorUtils?
     
  50. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Ah yes, we exploited the rounded rectangles feature to implement circles and ellipses... but I can absolutely understand that this will cause confusion.

    Using a Rectangle struct with straight corners will be more efficient than a Shape since this will take a fast path during tessellation to generate a single quad. If the Rectangle has rounded corners it will be converted into a Shape internally (its contour will be built using the VectorUtils.BuildRectangleContour() method), so this won't be more efficient.
     
    Last edited: Jul 6, 2018