Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by DavidPistorius · Apr 08 at 10:41 AM · 2dprogramming

I am trying to implement a fill style on a 2D rectangle object.

Hi,


Our company is busy moving one of our projects from a WPF application to a Unity 2D application. some of the functionality we a are working on is to implement a fill colour, pattern, and pattern colour on a rectangle object.


We have 7 different patterns which we implement.

  • Crosshatch

  • SquareHatch

  • Forward diagonal

  • Backward Diagonal

  • Vertical line

  • Horizontal Line

  • dotted.


the images provided are from the WPF application which we build the patterns using the .net class StreamGeometry.


alt text


alt text


As I am new to unity are there any built-in classes that behave similarly to StreamGeometry class? what would the best way of doing this in code?


squarehatch.png (11.0 kB)
crosshatchpattern.png (5.3 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Bunny83 · Apr 08 at 12:27 PM

are there any built-in classes that behave similarly to StreamGeometry class?

No, not really as Unity is a game engine. Most of the patterns you talk about come from the GDI brushes. However you can create your own texture, make it tilable and just set your UV coordinates accordingly and you should get the same effect.


Of course another option is to write a shader that produces the desired pattern. For example through a signed distance field (SDF) It's just a matter of getting fancy with math ^^.


Just as an example, about a week ago I made a quick and dirty (about) to scale diagram of our sun-earth-moon system in order to see the actual umbra and preumbra of the earth shadow. The whole thing is just a single fullscreen "RawImage" with this shader:

 Shader "Unlit/SolarSystemShader"
 {
     Properties
     {
         _MainTex ("Texture", 2D) = "white" {}
         _SunPos("SunPos", Vector) = (0,0,0,1)
         _SunSize("SunSize", float) = 140
         _EarthPos("EarthPos", Vector) = (15000,0,0,1)
         _EarthSize("EarthSize", float) = 1.2
         _MoonPos("MoonPos", Vector) = (15038.44,0,0,1)
         _MoonSize("MoonSize", float) = 0.3474
     }
     SubShader
     {
         Tags { "RenderType"="Opaque" }
         LOD 100
 
         Pass
         {
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             // make fog work
             #pragma multi_compile_fog
 
             #include "UnityCG.cginc"
 
             struct appdata
             {
                 float4 vertex : POSITION;
                 float2 uv : TEXCOORD0;
             };
 
             struct v2f
             {
                 float2 uv : TEXCOORD0;
                 float4 vertex : SV_POSITION;
             };
 
             sampler2D _MainTex;
             float4 _MainTex_ST;
             float4 _SunPos;
             float _SunSize;
             float4 _EarthPos;
             float _EarthSize;
             float4 _MoonPos;
             float _MoonSize;
 
             float3 _CamPos;
             float _Aspect;
             float _Scale;
 
 
             v2f vert (appdata v)
             {
                 v2f o;
                 o.vertex = UnityObjectToClipPos(v.vertex);
                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                 return o;
             }
 
             fixed4 drawCircle(float3 uv, float3 pos, float4 col, float size)
             {
                 pos = uv - (pos - _CamPos)/_Scale;
                 size /= _Scale*2;
                 float d = sqrt(pos.x * pos.x + pos.y * pos.y);
                 d = smoothstep(1-size, 1-size + 0.003, 1-d);
                 return d * col;
             }
             fixed4 drawLine(float3 uv, float3 pos, float3 normal, float4 col, float size)
             {
                 pos = uv-(pos - _CamPos) / _Scale;
                 float d = abs(dot(pos, normal));
                 d = smoothstep(1-size, 1-size + 0.001, 1-d);
                 return d * col*0.2;
             }
             fixed4 drawLineRepeat(float3 uv, float3 pos, float3 normal, float4 col, float size)
             {
                 pos = uv + _CamPos /_Scale;
                 pos.x = frac(pos.x/100 * _Scale)*100/_Scale;
                 float d = abs(dot(pos, normal));
                 d = smoothstep(1 - size, 1 - size + 0.00001, 1 - d);
                 d *= smoothstep(0.001, 0.002, 0.1-abs(pos.y));
                 return d * col * 0.2;
             }
 
             fixed4 frag(v2f i) : SV_Target
             {
                 float3 uv = float3(i.uv-0.5,0);
                 uv.x *= _Aspect;
                 fixed4 col = drawCircle(uv, _SunPos.xyz, float4(1, 1, 0.5, 1), _SunSize);
                 col += drawCircle(uv, _EarthPos.xyz, float4(0.5, 0.5, 1, 1), _EarthSize);
                 col += drawCircle(uv, _MoonPos.xyz, float4(0.5, 0.5, 0.5, 1), _MoonSize);
                 col += drawLine(uv, _SunPos.xyz, float3(1, 0, 0), float4(1, 0.5, 0.5, 0.1), 0.002);
                 col += drawLine(uv, _SunPos.xyz, float3(0, 1, 0), float4(1, 0.5, 0.5, 0.1), 0.002);
                 col += drawLine(uv, _EarthPos.xyz, float3(1, 0, 0), float4(1, 0.5, 0.5, 0.1), 0.002);
                 col += drawLine(uv, _MoonPos.xyz, float3(1, 0, 0), float4(1, 0.5, 0.5, 0.1), 0.002);
 
 
                 float3 p1 = float3(0, _SunSize*0.5 , 0);
                 float3 p2 = float3(_EarthPos.x, _EarthSize * 0.5, 0);
                 float3 n = normalize(cross(p1-p2, float3(0,0,1)));
                 col += drawLine(uv, p1, n, float4(0, 1, 0, 0.1), 0.002);
                 col += drawLine(uv, p1, float3(0, 1, 0), float4(0.5, 0.5, 1, 0.1), 0.002);
                 n.y = -n.y;
                 p1.y = -p1.y;
                 col += drawLine(uv, p1, n, float4(0, 1, 0, 0.1), 0.002);
                 col += drawLine(uv, p1, float3(0, 1, 0), float4(0.5, 0.5, 1, 0.1), 0.002);
                 n = normalize(cross(p1 - p2, float3(0, 0, 1)));
                 col += drawLine(uv, p1, n, float4(1, 1, 0, 0.1), 0.002);
                 n.y = -n.y;
                 p1.y = -p1.y;
                 col += drawLine(uv, p1, n, float4(1, 1, 0, 0.1), 0.002);
 
                 float3 p = 0;
                 col += drawLineRepeat(uv, p, float3(1,0,0), float4(1, 1, 0, 0.1), 0.002);
                 
                 return col;
             }
             ENDCG
         }
     }
 }

Besides that there is this simply script for the interaction. All it does is setting the "vitual" camera position and scale in the shader so you can pan around and zoom in and out. Though the whole diagram is just a single fullscreen UI.RawImage that does not move in screenspace.


Here's the script that does the panning and zooming:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 [ExecuteInEditMode]
 public class SolarSystem : MonoBehaviour
 {
     public Material mat;
     public Vector3 camPos;
     public float z = 1f;
 
     float aspect;
 
     void Update()
     {
         if (mat == null)
             return;
         aspect = Screen.width / (float)Screen.height;
         mat.SetVector("_CamPos", camPos);
         mat.SetFloat("_Aspect", aspect);
         mat.SetFloat("_Scale", z);
 
     }
     private void OnGUI()
     {
         var screenSizeInv = new Vector3(1f / Screen.height, -1f / Screen.height, 1);
         Event e = Event.current;
         var mPos = Vector3.Scale(e.mousePosition, screenSizeInv) - new Vector3(0.5f*aspect, -0.5f, 0);
         GUILayout.BeginVertical("box");
         float dist = (camPos.x + mPos.x * z)*10000;
         GUILayout.Label("dist from sun: " + (dist.ToString("000,000,000km",System.Globalization.CultureInfo.InvariantCulture)));
         GUILayout.Label("blue lines: horizontal to sun\ngreen lines: tangents of sun and earth\nyellow lines: crossing tangents");
         GUILayout.EndVertical();
         if (e.isMouse && Input.GetMouseButton(0))
         {
             var d = new Vector3(e.delta.x * screenSizeInv.x, e.delta.y * screenSizeInv.y);
             camPos -= d*z;
         }
         else if (e.type == EventType.ScrollWheel)
         {
             var delta = (camPos + mPos * z);
             if (e.delta.y <0)
                 z /= 1.1f;
             else
                 z *= 1.1f;
             z = Mathf.Clamp(z, 0.00001f, 20000f);
             camPos = (delta - mPos*z);
         }
         camPos.y = Mathf.Clamp(camPos.y, -150, 150);
         camPos.x = Mathf.Clamp(camPos.x, -150, 15100);
     }
 }
 

Note I just posted this as an example. In your case what you're most likely interested in is the "drawLineRepeat" approach which draws the repeated yellow markers every 1 million kilometers. The "scale" of one unit (when we talk about the camera position and the position of the earth and moon) is given in one unit == 10000km. In your case it probably makes more sense to write a surface shader and use the screenspace position of a fragment, though it depends on your exact needs. The shader examples page has some great examples which may help in case you want to go down this route.


Though using an actual texture and let it tile across a quad may be enough for your usecase. Though we don't know enough about your exact usecase so it's quite difficult to recommend a particular method.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by DavidPistorius · Apr 08 at 12:45 PM

I have managed to do the easier ones of the patterns, horizontal, vertical, and squarehatch patterns. using the UILineRenderer from the unity-ui-extensions. by creating a number of vector pairs representing the lines and using a line list.

by doing the following for the horizontal.

 private Dictionary<int, Vector2[]> BuildHorizontalHatchPattern(Vector3 startPoint, Vector3 endPoint)
         {
             var returnValue = new Dictionary<int, Vector2[]>();
             var size = new Vector2(Mathf.Abs(startPoint.x - endPoint.x),
                 Mathf.Abs(startPoint.y - endPoint.y));
             var lineStartPoint = new Vector2(0, LineSpacing);
             var lineEndPoint = new Vector2(size.x - LineLengthOffset, LineSpacing);
             var verticalLineCount = size.y / LineSpacing;
 
             for (var i = 0; i < verticalLineCount; i++)
             {
                 if (!returnValue.ContainsKey(i))
                 {
                     returnValue.Add(i, new []{lineStartPoint, lineEndPoint});
                 }
 
                 lineStartPoint += new Vector2(0, LineSpacing);
                 lineEndPoint += new Vector2(0, LineSpacing);
             }
             return returnValue;
         }

and this for the Vertical.

  private Dictionary<int, Vector2[]> BuildVerticalHatchPattern(Vector3 startPoint, Vector3 endPoint)
         {
             var returnValue = new Dictionary<int, Vector2[]>();
             var size = new Vector2(Mathf.Abs(startPoint.x - endPoint.x),
                 Mathf.Abs(startPoint.y - endPoint.y));
             var lineStartPoint = new Vector2(LineSpacing, 0);
             var lineEndPoint = new Vector2(LineSpacing, size.y - LineLengthOffset);
             var horizontalLineCount = size.x / LineSpacing;
 
             for (var i = 0; i < horizontalLineCount; i++)
             {
                 if (!returnValue.ContainsKey(i))
                 {
                     returnValue.Add(i, new []{lineStartPoint, lineEndPoint});
                 }
 
                 lineStartPoint += new Vector2(LineSpacing, 0);
                 lineEndPoint += new Vector2(LineSpacing, 0);
             }
             return returnValue;
         }

and this for the squarehatch.

 private Dictionary<int, Vector2[]> BuildSquareHatchPattern(Vector3 startPoint, Vector3 endPoint)
         {
             var returnValue = new Dictionary<int, Vector2[]>();
             var size = new Vector2(Mathf.Abs(startPoint.x - endPoint.x),
                 Mathf.Abs(startPoint.y - endPoint.y));
             var lineStartPoint = new Vector2(LineSpacing, 0);
             var lineEndPoint = new Vector2(LineSpacing, size.y - LineLengthOffset);
             var horizontalLineCount = size.x / LineSpacing;
 
             for (var i = 0; i < horizontalLineCount; i++)
             {
                 if (!returnValue.ContainsKey(i))
                 {
                     returnValue.Add(i, new []{lineStartPoint, lineEndPoint});
                 }
 
                 lineStartPoint += new Vector2(LineSpacing, 0);
                 lineEndPoint += new Vector2(LineSpacing, 0);
             }
             
             lineStartPoint = new Vector2(0, LineSpacing);
             lineEndPoint = new Vector2(size.x - LineLengthOffset, LineSpacing);
             var verticalLineCount = size.y / LineSpacing;
 
             for (var i = returnValue.Count; i < horizontalLineCount + verticalLineCount; i++)
             {
                 if (!returnValue.ContainsKey(i))
                 {
                     returnValue.Add(i, new[] { lineStartPoint, lineEndPoint });
                 }
 
                 lineStartPoint += new Vector2(0, LineSpacing);
                 lineEndPoint += new Vector2(0, LineSpacing);
             }
 
             return returnValue;
         }

and update the UILineRenderer to do the following.

 private void GetFillStyleCoordinates(FillStyles fillPatternType, Vector3 startPoint, Vector3 endPoint)
     {
         var pointDictionary = _fillsStyleProvider.GetFillStyle(fillPatternType, startPoint, endPoint);
         if (pointDictionary == null) return;
         
         var lineSegments = new List<Vector2[]>();
         var linePoints = new List<Vector2>();
         for (var i = 0; i < pointDictionary.Count; i++)
         {
             var points = pointDictionary[i];
             if (points == null)
             {
                 continue;
             }
            
             linePoints.AddRange(points);
             lineSegments.Add(points);
         }
 
         fillPatternLineRenderer.Points = linePoints.ToArray();
         fillPatternLineRenderer.Segments = lineSegments;
     }

Please note: this code is still a work in progress, and nowhere near complete.

However, I don't really understand how to create a dotted pattern and a forward or backward diagonal line or the crosshatch which is the forward and backward diagonal patterns combined.

Could anybody help me with this? Please

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

359 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

How to drag and drop in 2D game 0 Answers

How do the change the distance of a 2D universal pipeline light from a script? 0 Answers

While loop ignores conditions in coroutine 1 Answer

Animation or programming? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges