Jump to content
Unity Insider Forum

UI Bezier Curve


Recommended Posts

Moin,

ich hätte gerne Bezier Kurven im Unity UI die zur Runtime erstellt und verändert werden.
GIbt es da irgendeine performante und einfache Möglichkeit, die einzige Möglichkeit (leider in Unity ja nicht so performant) die mir einfällt ist während der Runtime die Textur zu generieren.

Über Ideen oder Anreize würde ich mich freuen (Bitte keine Plugins oder Asset Store Sachen, ich möchte das selber programmieren)

MfG KingEldarion

Link zu diesem Kommentar
Auf anderen Seiten teilen

So ich habe versucht einen Shader zu schreiben um mir eine Bezierre Kurve zu zeichnen, leider nur mit mäßigem Erfolg.

Ich weiß nicht ob ich irgendwas übersehe oder zu kompliziert denke aber mein Ansatz in dem Shader war folgender:

Da ich in einem Shader ja quasi immer nur einen aktuellen Pixel zeichne, brauche ich ja quasi in meinem Shader eine entsprechende Logik: Bin ich auf der Bezierre Kurve oder nicht?

Da ich auf den ersten Anhieb zu dieser Fragestellung nichts im Internet gefunden habe, habe ich mir angefangen selber Gedanken zu machen. Ich habe mir die normale Bezierre Formel für eine quadratische Kurve angeschaut und sie nach t hin umgestellt. Und wenn t für jeweils x und y relativ ähnlich sind, dann liegt der Punkt auf der Kurve.

So weit so gut, das hat auch funktioniert und spuckt logische Werte aus.

Das ganze im Shader berechnet, tendenziell ein Ergebnis das auf eine Kurve schließen lässt, aber irgendwie sieht meine Kurve dreidimensional aus, obwohl ich nur mit Vector2 rechne. Meiner Idee nach sieht das ganze aber nur nach einer Zufall aus, das es dreidimensional wirkt und irgendwie ein cooler Effekt aber den will ich garnicht.

Hier mal um ein Bild davon zu bekommen:

https://e87i.imgup.net/bezierreTrfe53.png

Interessant übrigens oberhalb des höchsten Punktes der zu sehenden Kurve springt das berechnete t immer unter 0! Das ist  zumindest der Grund warum es nach oben hin "abgehackt" aussieht.

Bei der Google Suche hab ich dann irgendwann folgendes gefunden, das meine bisherige Theorie aber eher legitimiert hat:

http://polymathprogrammer.com/2012/04/03/does-point-lie-on-bezier-curve/

Dort hab ich auch noch den Ansatz gefunden, nicht die t werte selber zu vergleichen, sondern diese wieder in die normale Bezierre Gleichung einzusetzen und den herauskommenden Punkt mit dem aktuellen zu vergleichen. Das Ergebnis sah zwar schon ein bisschen besser aus, aber trotzdem noch nicht gut genug :(

Falls jemand einen besseren Weg kennt eine Bezierre Kurve im Shader zu zeichnen oder weiß wie ich diesen Effekt aus meinem raus bekomme, würde ich mich echt freuen, habe die letzten beiden Tage dauerhaft dran gesessen und bin jetz grade am Ende meiner Gedanken. Und des weiteren gilt: Keine Line Renderer oder andere Unity interne Sachen, ich will alles selber machen oder garnix!

Hier mal mein Shader Code (Ich bin noch nicht ganz so fit mit Shadern habe erst vor ein paar Monaten langsam damit angefangen, die Textur ist nur drin, damit ich die uv bekomme, falls jemand da einen anderen Weg kennt, gerne her damit :D):

Shader "Custom/BezierCurve2" {

	Properties {
		
		_Color ("Color", Color) = (1,1,1,1)

		_StartPos ("Start Pos", Vector) = (0, 0, 0)
		_EndPos ("End Pos", Vector) = (0, 0, 0)
		_MidPos ("Mid Pos", Vector) = (0, 0, 0)
		_Dist ("Distance", Range(0,1)) = 0.1

		_UselessTex("Useless", 2D) = "white" {}
	}

	SubShader {
		
		Tags { 
			"RenderType"="Transparent"
		 	"Queue"="Overlay" 
		 	"IgnoreProjector"="True"
		 	"CanUseSpriteAtlas"="True"
		}

		LOD 200
		
		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows alpha:fade

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		struct Input {

			float2 uv_UselessTex;
		};

		fixed4 _Color;

		half4 _StartPos;
		half4 _EndPos;
		half4 _MidPos;
		half _Dist;

		void surf (Input IN, inout SurfaceOutputStandard o) {
			
			half2 startPos = _StartPos.xy;
			half2 endPos = _EndPos.xy;
			half2 midPos = _MidPos.xy;

			half2 curPos = IN.uv_UselessTex;

			if(startPos.x - 2 * midPos.x + endPos.x == 0){

				midPos.x -= 0.001F;
			}

			if(startPos.y - 2 * midPos.y + endPos.y == 0){

				midPos.y -= 0.001F;
			}

			half txp = (+sqrt(-startPos.x * endPos.x + startPos.x * curPos.x + pow(midPos.x, 2) - 2 * midPos.x * curPos.x + endPos.x * curPos.x) - startPos.x + midPos.x)
					/ (-startPos.x + 2 * midPos.x - endPos.x);

        	half txn = (-sqrt(-startPos.x * endPos.x + startPos.x * curPos.x + pow(midPos.x, 2) - 2 * midPos.x * curPos.x + endPos.x * curPos.x) - startPos.x + midPos.x)
					/ (-startPos.x + 2 * midPos.x - endPos.x);

        	half typ = (+sqrt(-startPos.y * endPos.y + startPos.y * curPos.y + pow(midPos.y, 2) - 2 * midPos.y * curPos.y + endPos.y * curPos.y) - startPos.y + midPos.y)
					/ (-startPos.y + 2 * midPos.y - endPos.y);

        	half tyn = (-sqrt(-startPos.y * endPos.y + startPos.y * curPos.y + pow(midPos.y, 2) - 2 * midPos.y * curPos.y + endPos.y * curPos.y) - startPos.y + midPos.y)
					/ (-startPos.y + 2 * midPos.y - endPos.y);
			
			half dif1 = abs(txp - tyn);
			half dif2 = abs(txp - typ);
			half dif3 =	abs(txn - typ);
			half dif4 = abs(txn - tyn);

			half minDif = min(dif1, min(dif2, min(dif3, dif4)));

			half bestT = -1;

			if(minDif == dif1){
				
				bestT = tyn + (txp - tyn) / 2;
			}
			else if(minDif == dif2){
				
				bestT = typ + (txp - typ) / 2;
			}
			else if(minDif == dif3){

				bestT = typ + (txn - typ) / 2;
			}
			else if(minDif == dif4){
				
				bestT = tyn + (txn - tyn) / 2;
			}

			//bestT = txn;

			//if(true){
			if(bestT >= 0 && bestT <= 1){
				
				half tPointX = pow(1 - bestT, 2) * startPos.x + 2 * (1 - bestT) * bestT * midPos.x + pow(bestT, 2) * endPos.x;
				half tPointY = pow(1 - bestT, 2) * startPos.y + 2 * (1 - bestT) * bestT * midPos.y + pow(bestT, 2) * endPos.y;
				
				half2 tPoint = half2(tPointX, tPointY);

				half2 curToBest = tPoint - curPos;

				if(pow(curToBest.x, 2) + pow(curToBest.y, 2) < pow(_Dist, 2)){
					
					o.Albedo = _Color.rgb;
					o.Alpha = 1;
				}
				else{

					o.Albedo = half3(0, 1, 0);
					o.Alpha = 0.0;
				}

				//o.Albedo = half3(tPoint.x, tPoint.y, bestT);
				//o.Alpha = 1;
			}
			else if(bestT == -1){

				o.Albedo = half3(1, 1, 1);
				o.Alpha = 0;
			}
			else{

				o.Albedo = half3(0, 0, 1);
				o.Alpha = 0;
			}


			//o.Albedo = bestT;
			//o.Alpha = 1;
		}

		ENDCG
	}

	FallBack "Diffuse"
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...