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

06.11.2011, 12:43

Dithering im Fragment Shader

Hallo :)

Da ich teilweise mit starkem und hässlichem Banding zu kämpfen habe, brauche ich einen Dithering-Shader.
Das normale glEnable(GL_DITHER) bewirkt nichts - zumindest sehe ich keinen Unterschied.
Nach etwas googlen habe ich herausgefunden, dass viele Dithering-Algorithmen nicht für Pixel/Fragment Shader geeignet sind, da diese ja parallel berechnet werden.
Irgendwann hab ich dann auch diesen Thread bei zfx gefunden. Dort wird Dithering basierend auf zufälligem Noise verwendet (siehe 3.1 Dithering gegen Banding).
Dann hab ich mir aus unterschiedlichen Quellen einen Shader gebastelt, der mir zufälliges Noise für jeden Pixel liefert.

Hier ist der Shader (GLSL) und das Ergebnis ist im Anhang (sieht ganz gut aus finde ich).

HLSL-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#version 120 
uniform sampler2D tex;  
uniform float Seed; // Intervall [0.0,1.0]
uniform float ScreenWidth;

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}


void main (void)
{
    vec2 uv = gl_TexCoord[0].xy;    
    
    float Rand1 = ScreenWidth*uv.y+uv.x*Seed;
    float Rand2 = uv.x*uv.y;    
    
    vec3 R  = vec3 (rand(vec2(Rand1*0.41,Rand2*0.23)),rand(vec2(Rand1*0.29,Rand2*0.59)),rand(vec2(Rand1*0.53,Rand2*0.47)));

    gl_FragColor = vec4 (R,1.0);
}



So und meine Frage ist jetzt: Was muss ich mit dem Noise machen? Muss ich addieren, multiplizieren...?
Dazu habe ich leider kaum was gefunden und wenn, dann war es nur etwas um das Bild von einer höheren Farbtiefe in eine kleinere zu konvertieren. Ich will ja aber eine noch höhere Farbtiefe simulieren und nicht eine kleinere.

Wie muss ich da vorgehen?

Lg chaia
»Chaia*« hat folgendes Bild angehängt:
  • ColorFinal2.png

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

06.11.2011, 13:31

Dazu habe ich leider kaum was gefunden und wenn, dann war es nur etwas um das Bild von einer höheren Farbtiefe in eine kleinere zu konvertieren. Ich will ja aber eine noch höhere Farbtiefe simulieren und nicht eine kleinere.

Eigentlich doch schon! Das Rendering gibt erstmal Gleitkommazahlen als Farben aus, dein Display hat aber nur 8 Bits pro Farbkanal. Wenn du erstmal alles in einem 8-Bits-pro-Kanal-Format gerendert hast, ist es für Dithering doch schon zu spät, denn die Information ist weg (du könntest höchstens etwas faken). Also eigentlich müsstest du alles in ein Render-Target mit höherer Bittiefe rendern (z.B. 16 Bits pro Kanal, Integer oder Float) und dann einen Dithering-Algorithmus benutzen, um es auf deine 8 Bits pro Kanal umzurechnen.
Die Begründung, warum Dithering mit Pixel-Shadern nicht gehen soll, verstehe ich nicht. Auch wenn du ohne Shader renderst, macht die GPU das alles größtenteils parallel.

3

07.11.2011, 18:05

Mhmm gut, es macht Sinn, dass es schon zu spät ist, wenn alles bereits in 8 Bit pro Kanal vorliegt.
Um ein Rendertarget mit höherer Farbtiefe zu erstellen müsste ich es mir "selbst schreiben", da ich mir der SFML arbeite. Allerdings kenne ich mich nicht soo wirklich mit OGL aus, daher verschiebe ich das mal auf später.

Zitat

Die Begründung, warum Dithering mit Pixel-Shadern nicht gehen soll, verstehe ich nicht. Auch wenn du ohne Shader renderst, macht die GPU das alles größtenteils parallel.


Das habe ich jetzt schon in mehreren Foren gelesen, ebenso direkt in dem oben verlinkten Thread:

Zitat

Zwar sind viele Dithering-Algorithmen für die Implementierung in Hardware geeignet, für superparallele Architekturen wie heutige GPUs bleiben allerdings nur wenige zur Auswahl.


Das hängt irgendwie damit zusammen, dass pro Pixel ja ein Fehlerwert generiert wird, bei manchen Algorithmen der Fehlerwert der umliegenden Pixel allerdings in die Berechnung des aktuellen Pixels einfließt. Bin mir aber nicht sicher, ob ich da was durcheinander bringe^^

Lg

Werbeanzeige