Erfolgreiche Spieleentwicklung
Normal.g < 0.01 && Normal.b < 0.01)
{
gs_FragColor = texture2D(ScreenTexture,
gs_TexCoord[0].st) + texture2D(EmissiveTexture, gs_TexCoord[0].st);
}
// Normale vorhanden, Beleuchtung kann berechnet
// werden:
else
{
// Umrechnung der RGB-Farbwerte in
// xyz-Richtungswerte:
Normal = 2.0*Normal - vec3(1.0, 1.0, 1.0);
vec3 CameraSpacePos = texture2D
(CameraSpacePositionTexture, gs_TexCoord[0].st).xyz;
vec4 LightPos;
vec4 SpecularColor = texture2D(SpecularTexture,gs_TexCoord[0].st);
vec4 DiffuseLightColor = vec4(0.0, 0.0, 0.0, 1.0);
vec4 SpecularLightColor = vec4(0.0, 0.0, 0.0,1.0);
// Hilfsvariablen für die anstehenden
// Berechnungen:
vec3 NegPointLightDir;
float tempDot, SpecularIntensity, Dist, InvDist;
float DistanceBasedIntensity, tempValue;
// Beleuchtungsberechnungen durchführen:
for(int i = 0; i < NumLightsUsed; i++)
{
// direktionales Licht
if(LightCameraSpacePosAndRange[i].w < 0.0)
{
// Berechnungen durchführen
// (siehe Listing 2.4)
}
Else
// Punktlicht
{
// Berechnungen durchführen
// (siehe Listing 2.5)
}
}
// Resultat der Beleuchtungsberechnungen ausgeben:
gs_FragColor = SpecularLightColor +
texture2D(EmissiveTexture,
gs_TexCoord[0].st) +
texture2D(ScreenTexture,
gs_TexCoord[0].st) * DiffuseLightColor;
}
}
}
Listing 2.3: Deferred Lighting, Aufbau des Fragment Shaders
Bei der Durchführung der Beleuchtungsberechnungen greifen wir auf das Modell von Phong [4] zurück. Diffuse Reflexionen treten insbesondere an rauen Oberflächen auf und sind, wie in Abbildung 2.1 gezeigt, abhängig vom Einfallswinkel des Lichts.
Abbildung 2.1: Diffuse Reflexion
Spiegelnde Reflexionen treten an glatten (polierten, spiegelnden) Oberflächen auf. Wie in Abbildung 2.2 dargestellt, ist die Intensität der Spiegelung abhängig vom Winkel zwischen der Blickrichtung des Betrachters und der Richtung des reflektierten Lichtstrahls.
Abbildung 2.2: Spiegelnde Reflexion
Listing 2.4 demonstriert die Beleuchtung durch eine direktionale Lichtquelle, Listing 2.5 – die Beleuchtung durch ein Punktlicht. Im Unterschied zur direktionalen Beleuchtung ist bei einem Punktlicht die Einfallsrichtung der Lichtstrahlen abhängig von der Position des Oberflächenpixels relativ zur Lichtquelle. Die Lichtintensität selbst ist zudem abstandsabhängig.
// Berechnung des diffusen Reflexionsanteils:
tempDot = dot(Normal, NegLightDir[i]);
DiffuseLightColor += max(tempDot, 0.0)*LightColor[i];
// Berechnung des spiegelnden Reflexionsanteils (nach Phong):
if(tempDot > -0.7)
{
SpecularIntensity = max(-dot(2.0*tempDot*Normal-NegLightDir[i], ViewDirection), 0.0);
// Durch den (die) nachfolgenden Multiplikationsschritt(e)
// wird die Fläche der Spiegelung schrittweise
// verkleinert:
SpecularIntensity *= SpecularIntensity;
SpecularLightColor += SpecularIntensity*SpecularColor;
}
}
}
Listing 2.4 Direktionale Beleuchtung
// Entfernung des Pixels zur Lichtquelle sowie die Richtung
// des einfallenden Lichts berechnen:
NegPointLightDir = LightCameraSpacePosAndRange
[i].xyz - CameraSpacePos; Dist = length(NegPointLightDir);
// Entfernung ist zu groß; die Berechnungen können vorzeitig
// abgebrochen werden:
if(Dist > LightCameraSpacePosAndRange[i].w)
continue;
// Lichtintensiät in Abhängig von der Entfernung berechnen:
InvDist = 1.0/Dist;
NegPointLightDir *= InvDist;
tempValue = LightCameraSpacePosAndRange[i].w*LightCameraSpacePosAndRange[i].w;
DistanceBasedIntensity = max(0.0, (tempValue-Dist*Dist)/tempValue);
// Berechnung des diffusen Reflexionsanteils:
tempDot = dot(Normal, NegPointLightDir);
DiffuseLightColor += DistanceBasedIntensity*max(tempDot, 0.0)*LightColor[i];
// Berechnung des spiegelnden Reflexionsanteils (nach Phong):
if(tempDot > -0.7)
{
SpecularIntensity = max(-dot(2.0*tempDot*Normal-NegPointLightDir, ViewDirection), 0.0);
// Durch den (die) nachfolgenden Multiplikationsschritt(e)
// wird die Fläche der Spiegelung schrittweise
// verkleinert:
SpecularIntensity *= SpecularIntensity;
SpecularLightColor += DistanceBasedIntensity*SpecularIntensity*SpecularColor;
}
Listing 2.5: Punktlicht-Beleuchtung
Im Detail erklärt
OpenGL-Framebuffer- und -Renderbuffer-Objekte: http://www.spieleprogrammierung.net/2010/07/opengl-framebuffer-und-renderbuffer.html
2.4 Uniform-Buffer-Objekte
Eine wichtige Voraussetzung für die Performance einer 3-D-Anwendung besteht in einer möglichst effizienten Kommunikation zwischen dem Haupt- und den Shader-Programmen. An dieser Stelle kommen die mit [2] OpenGL 3.1 eingeführten
Weitere Kostenlose Bücher