2016-12-18 1 views
1

Ich versuche eine einfache 2D Light Engine auf meinem Spiel basierend auf libGDX zu implementieren. Die Idee ist, diese Light Engine ohne Shader zu erstellen. Ich habe nicht vor, für den Moment einen Schatten zu machen. Ich habe es geschaffen, eine Licht-Karte mit Dreiecken und Steigungen zu machen, aber das Problem ist, dass, wenn die Quelle mehr Lichts überlappt ich in diesem Bild wie einige Artefakt bekam:2D Licht diffuse Kartenartefakt

enter image description here

die gelbe Lichtquelle einen dunkel ist Producting Grenze bei der Überlappung der anderen Lichtquellen.

Ich verwende die folgende Mischung Funktion, die Lichter zu machen:

Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE); 

Gibt es eine Möglichkeit dieses dunklen Grenze loswerden?

Der Farbverlauf reicht von gelb bis schwarz volle Deckkraft. Als GL_ONE soll additiv sein, sollten die Farben nur heller werden oder?

Update 1:

Mit Shader wie von Nico Schertler erklärt ist auf jeden Fall besser, aber es gibt noch einige Parameter Ich bin nicht sicher.

enter image description here

hier ist das Fragment-Shader-I mit

void main() { 
    float intensity = 0.02; 
    vec2 pos = vPosition; 
    float dist = distance(pos, u_origin)/u_radius; 
    vec4 color = vec4(intensity * (vColor.rgb/((dist * dist) + 0.01)), 1); 
    gl_FragColor = color; 
} 

das Problem ist, ich kam, dass über die Konstanten nicht sicher bin intensity = 0.02 und 0.01 ich auf die Funktion hinzugefügt haben, um es schön aussehen . Außerdem ist die Radiusvariable jetzt das Maximum zwischen Bildschirmhöhe und -breite.

Update 2:

Ich habe schließlich für die folgende Gleichung entschieden:

void main() { 
    float dist = distance(vPosition, u_origin)/u_radius; 
    vec4 color = vec4((vColor.rgb)/(pow(dist, 2) + 0.01), vColor.a); 

    gl_FragColor = color; 
} 

Dann mit einer Okklusion Karte kombiniert (abzudunkeln unbeleuchtete Plätze) basiert auf der gleichen Gleichung. Hier ist die endgültige Ausgabe:

ambient + occlusion

+2

Das dunklere Band eine Illusion ist. Sie können die Werte gerne mit jedem Grafikeditor überprüfen und sehen, dass sie nicht dunkler sind. Zurzeit scheint es, dass Sie nicht mit sRGB rendern, aber Sie sollten. Auch andere Dinge, wie der quadratische Falloff, werden das wahrscheinlich überdecken. – ybungalobill

Antwort

2

Das ist sehr viel hängt davon ab, wie man die Lichter zu.

z. wenn Sie etwas verkürztes quadratische Funktion als die Helligkeit des Lichts verwenden (in Bezug auf den Abstand von der Mitte), also so etwas wie die:

enter image description here

Wenn Sie zwei Lichter hinzufügen, werden Sie dieses Profil erhalten:

enter image description here

enter image description here

In diesem Profil finden Sie eine klare Diskontinuität. Der Grund für diese Diskontinuität ist die Kürzung der ursprünglichen Funktion.Wahrscheinlich haben Sie also eine abgeschnittene Lichtfunktion in Ihrem Bild (sei es quadratisch, linear oder was auch immer), die den hellen Bereich im Schnittpunkt der beiden Lichter verursacht.

So, wie das zu lösen? Physikalisch korrekte Lichtverteilung fällt mit dem quadratischen Abstand (in 2D man könnte auch argumentieren, für eine lineare Abnahme) aus, x ist der Abstand von der Lichtquelle:

light = factor/x^2 

Es gibt zwei Probleme mit dieser Funktion. Erstens wird es nicht kompakt unterstützt. Das bedeutet, dass Sie einen unendlich großen Splat (oder mindestens so groß wie der Bildschirm) zeichnen müssten. Dies ist möglicherweise kein großes Problem. Sie können das Licht auch abschneiden, sobald es sehr klein wird. Das zweite Problem ist schwerwiegender. Wenn x zu 0 geht (d. H. Sie befinden sich direkt an der Lichtposition), können Sie diesen Wert nicht berechnen (er neigt zur Unendlichkeit, da die gesamte Lichtenergie auf einen Punkt ohne Fläche fokussiert ist). Es hängt also wirklich davon ab, was Sie mit der Lichtkarte machen wollen. Natürlich könnte man in ähnlicher Weise wie

light = factor/((x)^2 + epsilon) 

, regularisieren wo epsilon eine sehr kleine Zahl ist. Wenn Ihre Szene etwas ist, das von oben betrachtet wird, könnte dieses Epsilon die Höhe des Lichts über dem Boden (Quadrat) sein. Dann würden Sie ein Profil wie folgt erhalten:

enter image description here

Voila, keine Unterbrechungen. Aber Sie werden höchstwahrscheinlich einen Fragment-Shader benötigen, um dies zu erreichen.

Wenn Sie nicht über körperliche Korrektheit kümmern, könnte eine Gaußsche Splat auch gut aussehende Ergebnisse geben:

light = factor * exp(-x^2/variance) 
+0

Ich denke, ich bin gezwungen, einige Shader zu verwenden, ich werde versuchen mit Meshes und Shadern zu sehen, ob es besser aussieht –

+0

Ich habe versucht, die Funktionen zu verwenden (siehe mein Update) Sie gaben mir aber können Sie erklären, was 'factor',' variance' und 'espilon' werden auf die Parameter" radius "und" distance "angewendet. Thx –

+0

'Faktor' ist nur eine Skalierung, die normalerweise mit der Intensität des Lichts korreliert. "Varianz" ist die Varianz des Gaussian, die angibt, wie fokussiert das Licht ist. Sie sollten ein paar Parameter ausprobieren. Etwas in dem Bereich "Radius^2/4" bis "Radius^2/9" sollte gute Ergebnisse ergeben. 'epsilon' ist eine beliebige Zahl. Wie ich bereits erwähnt habe, könntest du es auf die virtuelle Höhe des Lichts über dem Boden einstellen. Es beeinflusst auch, wie steil die Helligkeit abfällt. Ich denke, ich habe in dem Beispiel 'epsilon = 1' verwendet. –