Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

29.05.2012, 21:35

GLSL 2D Schatten

Hi,
jetzt nach einer kleinen Einübung in GLSL möchte ich nun das Erlernte in ein richtiges Spiel einbauen, ein Tank Wars Klon. Dazu ist die Map in Tiles zufällig generiert und auch der Himmel, da das ganze eine Jump n' Run 2D-Welt mit Affen als Charakter sein soll. Das Spiel ist schon in seiner Funktionsweise fertig und auch die Grafik ist weitgehend fertig. Nur möchte ich das ganze jetzt so verbessern, dass die Sonne eine Punktlichtquelle darstellt und Schatten in die Welt bringt. Die Player sollen keinen Schatten werfen nur die Map und dort dunkel sein wo kein Licht hinkommt (à la teeworlds nur umgedreht, da die Öffnung oben ist).
Von anderen 2D Shader Projekten liest man häufig, dass dazu eine Shadow Textur erzeugt wird, die den Bildschirm ausfüllt. Die Lichter werden nacheinander verarbeitet und in die Shadow Textur eingefügt. Die Shadow Map wird dann über die Map gerendert und man hat die Schatten. Hier ist es einfacher, da es nur ein Licht gibt.
Aber wie bewerkstellige ich das jetzt nun?
Für das Zeichnen der eigentlichen Lichtquelle hab ich den Shader von diesem youtube-video gesehen, aber der Shader fügt keine Schatten ein. Ich habe mir gedacht ich lass die Teile die Licht blockieren in diese Shadow Map zusammen mit den Shader zeichnen und der Shader weiß dann wo die Schatten liegen. Nun kann ich ja eine Linie von dem jeweiligen Fragment zur Punktlichtquelle (sonne) berechnen aber wie weiß ich dass diese Linie von der Map blockiert wird?
Natürlich könnte ich jeden einzelnen Punkt auf dieser Linie überprüfen aber das wäre doch höchst ineffizient?
Wisst ihr dafür eine bessere Möglichkeit, oder wisst ihr allgemein eine bessere Möglichkeit sich dem Problem von 2D Schatten (mit Shadern) zu widmen?
Mfg Helco

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

29.05.2012, 21:45

Die Schatten in dem Video werden laut Beschreibung nicht durch einen Shader berechnet. Und das hat genau den Grund, den Du schon ansprichst. Die Beleuchtung da ist außerdem zwar interessant, sieht aber nicht sonderlich... korrekt aus. Klar, bunte Flecken und schwarze Bereiche, aber das würde mit einer Textur im Untergrund nicht wie Beleuchtung aussehen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

29.05.2012, 22:03

Um die 100% (oder auch nur 50%) korrekte Beleuchtung geht es mir auch nicht. Ich wüsste nur gerne eine Methode zur Berechnung der Schatten, am besten falls das möglich ist mit Shader (um mein Wissen über das Schreiben von Shadern zu erweitern und wegen der Geschwindigkeit)

idontknow

unregistriert

4

30.05.2012, 01:45

Du wirst halt irgendwie entweder ein schwarzes QUad drüber legen müssen und mit dem Shader die "Lichtstellen" ausschneiden oder eventuell mit dem Shader die Lichtstellen berechnen und entsprechend "verdunkeln" bis hin zu ganz schwarz einfärben. Wären zumindest meine 2 Ideen wobei die eigendlich identisch sind. Wie man das umsetzt weiß ich aber auch nicht, dazu fehlt mir dann doch die Ahnung von Shadern.

edit: andere Idee wobei die wohl nich sooo rasend wäre, aber für primitives Licht vielleicht gehen würde! Du renderst in eine Textur das Licht hinein und blendest dass mit deiner "Welt" zusammen. Problem ist halt, dass du die unbeleuchtbaren "Kanten" aus dem aus der "Lightmap" wiedrrum ausschneiden musst, also z.b. eine Wand oder sowas in der Art. Könntest du theoretisch aber vllt auch mit ner weiteren Textur machen in der du die Rechtecke reinrenderst und durch zusammenlegen mit der Lightmap eventuell die unbeleuchtbaren Stellen so ausschneidest. Ist aber nur ein Ansatz und hab wie gesagt sehr wenig Ahnung, deswegen kann das auch totaler Müll sein :P

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »idontknow« (30.05.2012, 01:52)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

30.05.2012, 06:55

Wie das aus dem Video funktioniert steht drunter, sagte ich ja auch bereits und ist für Deinen Zweck sicher absolut ungeeignet.
Eventuell solltest Du uns aber mal Deine Welt ohne Schatten zeigen, damit wir eine zu Deiner Geometrie passende Lösung vorschlagen können. Klar ist aber jetzt schon, dass Du die Schatten wohl nicht mit einem Shader berechnen können wirst, das Problem daran hast Du ja selbst schon erkannt, du müsstest Raycasting betreiben, was vielleicht als Pre-Rendering kein Problem ist, aber bei Echtzeit-Beleuchtung eher ungut kommt.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

6

30.05.2012, 07:12

Nun Pre-Rendering ist auch nicht schlecht. Ich wollte das ganze ja in eine Textur schreiben in der nur die Schatten vorhanden sind.
Die Welt wird in ihre Tiles zerstört werden im Spiel und nur dann soll die Shadow Map aktualisiert werden.
Die Welt ohne Charakter/GUI sieht so aus:

(Link)

P.S.: Im Blogeintrag von dem der das Video gemacht hat steht er würde die Schatten raycasten, im Pixel Shader steht davon leider kein wort...

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Helco« (30.05.2012, 07:21)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

30.05.2012, 08:04

Raycasting kann man auch machen, wenn man daraus dann Quads erstellt ;)

Kannst du in dem Bild mal skizzieren, wo und wie du die Schatten denn gern hättest? Generell wird es aber meiner Meinung nach ebenfalls auf einen Raycast hinauslaufen, der dann eine Textur füllt, die am Ende über alles drüber gerendert wird.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

8

30.05.2012, 11:09

Meine shader-basierende Lösung sieht so aus: http://www.splattergame.net/wp-content/g…eenshot0013.png Wie es funktioniert, habe ich u.a. schonmal hier beschrieben: WIP (Work in progress) - Postet Infos/Screenshots zu euren laufenden Projekten!

Arbeitet mit einer 4:1 reduzierten Auflösung, aber könnte auf modernen Grafikkarten für wenige Lichtquellen auch problemlos 1:1 klappen... wenn Du das denn brauchst. Ich bezweifle es. Ich würde an Deiner Stelle eher etwas weichere Schatten bevorzugen, weil die Ein-Pixel-Grasbüschel des Beispielbilds sonst sehr frickelige Schatten werfen würden.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

9

30.05.2012, 18:08

Okay, Danke für die Infos.
Raycasting per Pixelshader im Pre-Rendering wird wohl meine Wahl sein (auch durch die entstehende Universalität für weitere Projekte mit 2D Lichtern)
Ich habe nun eine weitere 512*512 Textur (genauso groß wie die Textur für die Map, erstmal bis das funktioniert, dann kann ich mir Gedanken machen über Größe reduzieren, dafür Filter drauf für bessere Perfomance vmt. sogar besseres Aussehen da die Schatten dann ja weicher sind) erstellt.
Die fertig gerenderte Map wird zusammen mit dem Shader in die neue Textur gepackt.
Der Vertex Shader ist nichts Besonderes, nur das Nötigste, da ich mehr im Vertex Shader auch nicht machen kann:

C-/C++-Quelltext

1
2
3
4
5
void main()
{
    gl_Position=ftransform();
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

Der Fragment Shader hat schon einiges, aber erst mal den Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
uniform sampler2D world;
uniform vec2 resolution;
uniform vec2 sun;

void main (void)
{
    float stepSize=160.0;
    vec4 texel=texture2D(world,gl_TexCoord[0].st);
    vec2 pos=vec2(floor(gl_FragCoord.x),floor(gl_FragCoord.y));
    vec2 texFac=vec2(1.0/resolution.x,1.0/resolution.y);
    if (texel.a!=0.0)
        discard;
    if (sun.y<pos.y)
        discard;
    float m=(sun.y-pos.y)/(sun.x-pos.x);
    vec2 checkPos=pos;
    vec2 checkTex;
    for (;checkPos.y<sun.y;checkPos.y+=stepSize*m) {
        checkTex.x=checkPos.x*texFac.x;
        checkTex.y=checkPos.y*texFac.y;
        texel=texture2D(world,checkTex);
        if (texel.a!=0.0)
            break;
        if (sun.x>pos.x)
            checkPos.x+=stepSize;
        else
            checkPos.x-=stepSize;
    }
    if (checkPos.y<sun.y)
        gl_FragColor=vec4(0.0,0.0,0.0,0.95);
    else
        discard;
}

Gegeben ist die Map, die Größe der Map (und damit die Größe der Shadow Map) und die Position der Sonne. Wenn das Fragment in der Map ist wird gleich mal abgebrochen, denn in der Map sieht man dann keine Schatten. Auch was oberhalb der Sonne ist braucht einem nicht zu interessieren weil oberhalb der Sonne nie etwas sein wird was Schatten werfen oder Schatten empfangen wird.
"stepSize" - Die Größe eines Iterationsschritt für das Raycasting ist schon eine "ich-versuch-einfachmal-komplett-bescheuerte-werte-weil-was-klügeres-nicht-funktioniert"-Variable. Angefangen hab ich mit 1.0
Des weiteren berechne ich am Anfang die Position (ohne Komma), die Faktoren die ich mit Texturpositionsangaben in Pixel multiplizieren muss um die Texturpositionsangaben in Prozent für die texture2D Funktion zu bekommen.
Nach den Tests gehts dann ans Raycasten also berechne ich die Steigung des Rays. Entlang des Rays möchte ich dann schauen ob er sich dort mit der Map schneidet (= kein Licht an den Ursprungsort kommt = Schatten)

Wenn ich den Shader allerdings ausführe, dauert es ca. 2 Sekunden, der Bildschirm wird kurz schwarz und eine Fehlermeldung des NVidia OpenGL Treibers meldet sich mit einer Fehlermeldung die mich auf diese Seite führt auf der die Fehlermeldung auch noch mal zu melden ist. Der Fehlermeldung glaubend habe ich also die Iterationsschrittgröße langsam bis auf 160 erhöht was keinen Unterschied machte.
Ich kenne mich leider (bis jetzt) kaum mit Shader und mit Raycasting schon gar nicht aus, deswegen frage ich euch: Seht ihr den Fehler?
Mfg Helco

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

31.05.2012, 06:49

Also was mir persönlich schonmal ungut aufstößt ist, dass Du da eventuell durch 0 dividierst.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige

Ähnliche Themen