Sprites skizzieren

9

Ich arbeite derzeit an einem 2D-Spiel und meine aktuelle Aufgabe ist es, ausgewählte Objekte zu skizzieren.

Ich benutze grundsätzlich einen Blur Shader, um es vollständig zur Laufzeit zu machen. Ich zeichne mein Sprite zuerst mit einem vertikalen Gaußschen Unschärfeshader, dann zeichne ich es mit einem horizontalen Gaußschen Unschärfeshader und dann zeichne ich mein Sprite normal.

Hier ist mein Blur Shader: Sampler TextureSampler: register (s0);

#define SAMPLE_COUNT 15

float2 SampleOffsets[SAMPLE_COUNT];
float SampleWeights[SAMPLE_COUNT];


float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 c = 0;

    // Combine a number of weighted image filter taps.
    for (int i = 0; i < SAMPLE_COUNT; i++)
    {
        c += tex2D(TextureSampler, texCoord + SampleOffsets[i]) * SampleWeights[i];
    }

    return c;
}

SampleOffets sind die Offsets, mit denen ich Rundungspixel testen kann. SampleWeights sind Gewichte, die mit der Gaußschen Funktion berechnet werden ( http://en.wikipedia.org/wiki/Gaussian_blur ).

Hier ist das Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Es ist nicht so schlimm, ziemlich glatt, aber im Spiel nicht genug sichtbar ... Aber ich möchte in der Lage sein, die Dicke zu kontrollieren (um sie zu vergrößern) und einen ersten undurchsichtigen Umriss hinzuzufügen, bevor ich sie in Alpha einblende (um sie zu machen) es sichtbarer). Und ich habe das Gefühl, dass Gaußsche Unschärfe vielleicht nicht so gut ist, wie ich für meine Aufgabe gedacht habe :)

Eine andere Idee ist es, es automatisch aus der PNG-Datei zu generieren (mit einem Photoshop-Skript, um es automatisch zu machen). Ich muss nur die Umrisspixel mit einer benutzerdefinierten Farbe füllen, den Alpha-Wert beispielsweise in der roten Komponente speichern und alle anderen Komponenten auf 0 setzen. Dann muss ich nur einen Shader anwenden, der transparente Pixel durch die gewünschte Farbe ersetzt

float4 PixelShaderFunction2(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 color = tex2D(TextureSampler, texCoord);
    float4 newColor = 0;
    if (color.a == 0 && color.r != 0)
    {
        color.a = color.r;
        // Blue outline
        color.b = 1;
    }
}

Das Problem ist, dass ich für mein Sprite die DXT5-Komprimierung verwende. Daher kann ich nicht sicher sein, ob die Farbe, die ich in meinem Shader bekomme, genau die gleiche ist, die ich geschrieben habe. Deshalb habe ich es nicht einmal versucht ... Irgendwelche Gedanken?

Jeder Rat wäre willkommen :)

s0ubap
quelle
Sie sollten in der Lage sein, die Dicke und den Alpha-Abfall in Ihrem Shader zu steuern. Möchten Sie es als Referenz veröffentlichen?
Seth Battin
Ich habe den Gaußschen Weichzeichnungs-Shader aus diesem Beispiel verwendet: Link : Lassen Sie mich meinen Beitrag bearbeiten, um Ihnen den Shader im Detail zu zeigen
s0ubap
Ich bin mir nicht sicher, ob die Gaußsche Unschärfe die richtige für Sie ist. Versuchen Sie stattdessen eine radiale Unschärfe.
user1306322

Antworten:

6

Was Sie wahrscheinlich suchen, ist eine Form der Kantenerkennung vor, nach oder sogar vor und nach Ihrer Gaußschen Unschärfe. Möglicherweise könnte eine Version von Sobel Edge Detection funktionieren. Ich weiß, dass Ihr Spiel 2D ist, aber wenn die Wiki-Seite zu rau ist, finden Sie hier ein Tutorial, wie Sie es im UDK zum Laufen bringen können , das möglicherweise besser übersetzt werden kann.

Ihre Kantenerkennung muss nur dann wirklich die Kanten des Alphakanals finden, wenn Sie eine Geschwindigkeitssteigerung benötigen.

Alex Shepard
quelle
Interessant! Ich versuchte es. Das Ergebnis war gut, außer wenn ich hinein- /
herauszoome
1
Was für ein Artefakt sehen Sie? Können Sie ein Bild bereitstellen?
Alex Shepard
2

Was für mich mit Textkonturen funktionierte, war:

  • Wählen Sie die Umrissfarbe
  • Zeichnen Sie den Text bei (x-1, y-1) mit Umrissfarbe
  • Zeichnen Sie den Text bei (x + 1, y-1) mit der Umrissfarbe
  • Zeichnen Sie den Text bei (x-1, y + 1) mit der Umrissfarbe
  • Zeichnen Sie den Text bei (x + 1, y + 1) mit der Umrissfarbe
  • Zeichnen Sie den Text bei (x, y)

Sie können das Gleiche tun - Sie müssen lediglich das Sprite mit den undurchsichtigen Pixeln zeichnen, die mit Ihrer Umrissfarbe gefärbt sind. (Behalten Sie die Transparenzwerte bei, damit die runden Kanten immer noch rund aussehen.)

Dies funktioniert, sieht besser aus als das Zeichnen einer skalierten Version und hat einige andere coole Eigenschaften (z. B. die Möglichkeit, das Umriss-Alpha auf Kühnheit zu steuern und alle "Löcher" in Ihrem Sprite-Bild beizubehalten) - der einzige Nachteil ist, dass Sie es können. Ich kann die Breite der Kontur nicht wirklich gut steuern.

Asche999
quelle
1

Ich bin ein bisschen neu in all dem, aber hier ist meine Idee:

Sie können den Alpha-Kanal Ihrer Textur verwenden, um eine andere Textur zu erstellen. Jeder Alpha-Wert unter einem Schwellenwert wird auf vollständig transparent gesetzt. Alle oben genannten sind vollständig undurchsichtig. Mit dieser neuen Textur können Sie die RGB-Werte auf eine beliebige Farbe einstellen. Skaliere diese neue "Textur" so, dass sie etwas größer ist als deine Charaktertextur. Dies würde Ihnen eine schöne Volltonfarbe um den Charakter geben. Verwenden Sie diese Farbe dann mit Ihrem Gaußschen Shader, um die erstellte Textur in einem schönen Umriss zu erhalten. Ich vermute, dies könnte geschehen, ohne eine andere Textur zu erstellen, und alles Shader basierend auf der Charaktertextur.

Ist das überhaupt sinnvoll?

Aglassman
quelle
Diese Methode weist einen großen Fehler beim Umgang mit nicht konkaven Formen auf. Wenn Sie beispielsweise auf einen Donut auftragen, erhält nur die Außenkante einen Umriss. Ganz zu schweigen von anderen Verzerrungen der Umrissdicke.
Kromster