shader Stereoscopy
Inhaltsverzeichnis
Stereoskopischer Post-Processing-Shader
Zurück zur Shadersammlung
Beschreibung | Autor | Version |
---|---|---|
Post-Processing-Shader für Stereoskopie | Joni | 1.0 |
Bilder
Oben: Half-Color Anaglyph; mitte: Horizontal Interlaced (funktioniert nur bei maximaler Bildauflösung); unten: Full-Color Anaglyph
Beschreibung
Die hier vorgestellten Shader konvertieren mit verschiedenen Verfahren ein linkes und ein rechtes Eingabebild in ein stereoskopisches Bild. In dem folgenden Abschnitt werden die einzelnen Verfahren näher erläutert.
Horizontal Interlaced
Bei der zeilenverschachtelten Stereoskopie sind alle ungeraden Pixelzeilen für das linke Auge und alle geraden Pixelzeilen für das rechte Auge bestimmt. Verwendet wird dieses Verfahren u. A. von den Zalman- und den Hyundai-3D-Bildschirmen.
Vertical Interlaced
Analog zur zeilenverschachtelten Stereoskopie wird hier nach ungeraden und geraden Spalten sortiert. Verwendet wird dieses Verfahren u. A. für den Druck auf Linsenrasterkarten.
Checkerboard
Hier gehören jeweils die Pixel, die diagonal zueinander liegen, zu einem Auge. Die Aufteilung erinnert an ein Schachbrett, daher der Name. Verwendet wird das Verfahren u. A. von einigen Fernsehen von Samsung in Kombination mit einer Shutterbrille.
Half-Color Anaglyphen
Das Half-Color-Verfahren ist ein Anaglyphen-Verfahren für rot/cyan-Brillen, das im gegenüber dem True-Color-Anaglyphen-Verfahren, was auch im Stereoskopie-Tutorial verwendet wird, einen nennenswerten Vorteil bei farbiger Szene hat. Bei dem True-Color-Verfahren wird für den roten Kanal des finalen Bildes der rote Kanal des linken Bildes genommen, was zu Konflikten bei roten Objekten in der Szene führt. Diese erscheinen dann auf dem linken Auge mit voller Helligkeit und auf dem rechten Auge schwarz. Das Half-Color-Verfahren verwendet daher für den roten Farbkanal des finalen Bildes nicht den roten Kanal des linken Bildes, sondern dessen Helligkeit, die wie bei Graustufen mit der folgenden Formel berechnet wird:
luminance = 0.299*red + 0.587*green + 0.114*blue
Der Nachteil dieses Verfahrens ist, dass die Farben etwas verfälscht werden.
Optimized Anaglyphen
Dieses Verfahren ähnelt dem Half-Color-Verfahren, ignoriert aber bei dem linken Bild den Rotanteil vollständig und berechnet den finalen roten Kanal folgendermaßen:
red = 0.7*green + 0.3*blue
Dieses Verfahren erstellt noch etwas ruhigere Bilder als das Half-Color-Verfahren, verfälscht die Farben aber auch stärker. Zusätzlich kann bei dem Verfahren noch Gammakorrektur auf den roten Kanal angewandt werden.
Besondere Vorraussetzungen
Um den Code sinnvoll zu benutzen, ist eine Anaglyphen-Brille oder ein stereoskopisches Gerät, das eins der o.g. Verfahren verwendet, nötig.
Anmerkungen
Für die Verwendung von Anaglyphen mit grün/magenta kann man die o.g. Verfahren entsprechend anpassen. Welches Verfahren sich dafür anbietet, ist zu testen, da der Autor keine solche Brille besitzt.
Das neu aufgekommene, patentierte ColorCode-Verfahren sieht zwar gelb/blauen Anaglyphen ähnlich, ist jedoch anders und nicht zu gelb/blau-Anaglyphen kompatibel. Da das Color-Code-Verfahren patentiert und nicht öffentlich bekannt ist, besteht leider keine Möglichkeit, es hier zu verwenden.
Für Shutterbrillen, Doppelprojektoren etc. ist man in OpenGL auf eine Treiberlösung angewiesen. Details dazu gibt es im Tutorial StereoSehen.
Code
Hier wird OpenGL 3.2 und GLSL-Version 1.5 verwendet, die Shader sollten jedoch problemlos mit jeder GLSL-Version funktionieren.
Vertex Shader
Da es sich um einen Post-Processing-Shader handelt, tut der Vertexshader nur das Nötigste: Er leitet Vertex- und Texturkoordinaten weiter.
#version 150
in vec3 in_Position;
in vec2 in_TexCoord;
out vec2 ex_TexCoord;
void main(void)
{
gl_Position = vec4(in_Position, 1.0);
ex_TexCoord = in_TexCoord;
}
Horizontal Interlaced
#version 150
precision highp float;
in vec3 ex_Color;
in vec2 ex_TexCoord;
out vec4 out_Color;
uniform sampler2D left; //Linkes Bild
uniform sampler2D right; //Rechtes Bild
void main(void)
{
//Horizontal Interlaced
if (mod(trunc(gl_FragCoord.y), 2.0) < 0.5)
out_Color = texture2D(left, vec2(ex_TexCoord));
else
out_Color = texture2D(right, vec2(ex_TexCoord));
}
Vertical Interlaced
#version 150
precision highp float;
in vec3 ex_Color;
in vec2 ex_TexCoord;
out vec4 out_Color;
uniform sampler2D left;
uniform sampler2D right;
void main(void)
{
//Vertical Interlaced
if (mod(trunc(gl_FragCoord.x), 2.0) < 0.5)
out_Color = texture2D(left, vec2(ex_TexCoord));
else
out_Color = texture2D(right, vec2(ex_TexCoord));
}
Checkerboard
#version 150
precision highp float;
in vec3 ex_Color;
in vec2 ex_TexCoord;
out vec4 out_Color;
uniform sampler2D left;
uniform sampler2D right;
void main(void)
{
//Checkerboard
bool d1 = (mod(trunc(gl_FragCoord.x), 2.0) < 0.5);
bool d2 = (mod(trunc(gl_FragCoord.y), 2.0) < 0.5);
if (d1==d2)
out_Color = texture2D(left, vec2(ex_TexCoord));
else
out_Color = texture2D(right, vec2(ex_TexCoord));
}
Half-Color-Anaglyph
#version 150
precision highp float;
in vec3 ex_Color;
in vec2 ex_TexCoord;
out vec4 out_Color;
uniform sampler2D left;
uniform sampler2D right;
void main(void)
{
//Half-Color Anaglyphen
vec3 cleft = texture2D(left, vec2(ex_TexCoord)).xyz;
vec3 cright = texture2D(right, vec2(ex_TexCoord)).xyz;
out_Color.r = 0.299*cleft.r + 0.587*cleft.g + 0.114*cleft.b; //Half-Color
out_Color.g = cright.g;
out_Color.b = cright.b;
}
Optimized-Anaglyph
#version 150
precision highp float;
in vec3 ex_Color;
in vec2 ex_TexCoord;
out vec4 out_Color;
uniform sampler2D left;
uniform sampler2D right;
void main(void)
{
//Half-Color Anaglyphen
vec3 cleft = texture2D(left, vec2(ex_TexCoord)).xyz;
vec3 cright = texture2D(right, vec2(ex_TexCoord)).xyz;
out_Color.r = 0.7*cleft.g + 0.3*cleft.b; //ohne Gammakorrektur
out_Color.r = pow(0.7*cleft.g + 0.3*cleft.b, 1.5); //mit Gammakorrektur
out_Color.g = cright.g;
out_Color.b = cright.b;
}
Links
http://www.3dtv.at/knowhow/AnaglyphComparison_en.aspx