shader Bumpmapping: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Code)
K (Beschreibung: TBN Matrix verlinkt)
 
(9 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 6: Zeile 6:
 
!width=20%|Version
 
!width=20%|Version
 
|-
 
|-
|Beleuchtet Primitiven per Pixel unter der zuhilfenahme einer Normalmap um einen Bumpmapping Effekt zu erzeugen.
+
|per-Pixel-Beleuchtung unter Zuhilfenahme einer Normalmap um einen Bumpmapping Effekt zu erzeugen.
 
|Bergmann
 
|Bergmann
 
|1.0
 
|1.0
Zeile 21: Zeile 21:
  
 
==Beschreibung==
 
==Beschreibung==
foglt noch
+
Der Bumpmapping Shader basiert auf dem [[shader_PerPixelLighting|Per Pixel-Beleuchtung]]-Shader. Der Unterschied zu diesem besteht darin, das wir die Normale nicht einfach so benutzen, wie sie an den Shader übergeben wurde, sondern wir sie erst mit den Daten aus der NormalMap manipulieren müssen. Dazu basteln wir uns eine [[TBN Matrix]] aus der Sicht der Textur zusammen: x-Achse = Tangente, y-Achse = Bitangente und z-Achse = Normale.Die Berechnung der Vektoren erfolgt gemäß [http://hacksoflife.blogspot.com/2009/11/per-pixel-tangent-space-normal-mapping.html diesem Artikel].
 +
 
 +
Um weiter zu rechnen setzen wur nun die 3 Achsen zu einer Matrix zusammen:
 +
<source lang="glsl">mat3 M = mat3(T, B, N);</source>
 +
 
 +
 
 +
Um die Normale zu erzeugen, welche dann zur Lichtberechnung genutzt wird lesen wir zunächst die Daten aus der NormalMap. Da die Farbewerte immer im Bereich [0..1] liegen, eine Normale aber immer in alle Richtungen zeigen kann und nicht nur in die positiven, müssen wir von jedem Farbewert noch 0.5 abziehen und den Farbvektor dann normalisieren. Dann multiplizieren wir noch mit der zuvor erzeugten Matrix und der NormalMatrix:
 +
<source lang="glsl">vec3 normal = normalize((vec3(texture2D(Texture1, TexCoord)) - vec3(0.5, 0.5, 0.5)) * M);
 +
normal = gl_NormalMatrix * normal;</source>
  
 
==Code==
 
==Code==
Zeile 32: Zeile 40:
 
{
 
{
 
gl_TexCoord[0]  = gl_MultiTexCoord0;
 
gl_TexCoord[0]  = gl_MultiTexCoord0;
N         = normalize(gl_Normal);
+
N         = normalize(gl_NormalMatrix * gl_Normal);
V = vec3(gl_ModelViewMatrix * gl_Vertex);
+
V = vec3(gl_ModelViewMatrix * gl_Vertex);
 
for(int i = 0; i < LIGHT_COUNT; i++){
 
for(int i = 0; i < LIGHT_COUNT; i++){
 
lightvec[i] = normalize(gl_LightSource[i].position.xyz - V);
 
lightvec[i] = normalize(gl_LightSource[i].position.xyz - V);
Zeile 39: Zeile 47:
 
gl_Position    = gl_ModelViewProjectionMatrix * gl_Vertex;
 
gl_Position    = gl_ModelViewProjectionMatrix * gl_Vertex;
 
}</source>
 
}</source>
 +
  
 
Fragmentshader:
 
Fragmentshader:
<source lang="glsl">const float PI = 3.14159265;       //Pi, zur Berechnung der Rotation
+
<source lang="glsl">const int LIGHT_COUNT = 1;
const int LIGHT_COUNT = 1;          //Anzahl der berücksichtigten Lichter
+
const float PI = 3.14159265;
varying vec3 N;                     //NormalenVektor
+
varying vec3 N;
varying vec3 V;                     //VertexVektor
+
varying vec3 V;
varying vec3 lightvec[LIGHT_COUNT]; //LichtVektor(en)
+
varying vec3 lightvec[LIGHT_COUNT];
uniform sampler2D Texture0;         //normale Textur
+
uniform sampler2D Texture0;
uniform sampler2D Texture1;         //NormalMap
+
uniform sampler2D Texture1;
 
 
//dreht einen Punkt um eine Achse im Raum
 
//@a: Achse um die gedreht wird
 
//@p: Punkt der gedreht werden soll
 
//@rad: Winkel im BogenMaß
 
vec3 rotate(vec3 a, vec3 p, float rad){
 
vec3 p1 = cos(rad) * p +
 
          sin(rad) * cross(a, p);
 
return p1;
 
}
 
  
 
void main(void){
 
void main(void){
 
vec2 TexCoord = vec2(gl_TexCoord[0]);
 
vec2 TexCoord = vec2(gl_TexCoord[0]);
vec3 G = normalize(vec3(dFdx(TexCoord.s), dFdy(TexCoord.t), 0.0));
+
vec3 Eye = normalize(-V);
vec3 B = normalize(rotate(N, cross(N, G), -0.25*PI));
+
 
vec3 T = normalize(cross(B, N));
+
vec3 q0 = dFdx(Eye.xyz);
mat3 M = mat3(T, B, N);
+
vec3 q1 = dFdy(Eye.xyz);
 +
vec2 st0 = dFdx(TexCoord.st);
 +
vec2 st1 = dFdy(TexCoord.st);
 
 
vec3 normal = normalize((vec3(texture2D(Texture1, TexCoord)) - vec3(0.5, 0.5, 0.5)) * M);
+
vec3 S = normalize( q0 * st1.t - q1 * st0.t);
normal = gl_NormalMatrix * normal;
+
vec3 T = normalize(-q0 * st1.s + q1 * st0.s);
 +
 +
mat3 M = mat3(-T, -S, N);
 +
vec3 normal = normalize(M * (vec3(texture2D(Texture1, TexCoord)) - vec3(0.5, 0.5, 0.5)));
 
 
vec3 Eye = normalize(-V);
 
 
vec4 EndColor = vec4(0.0, 0.0, 0.0, 0.0);
 
vec4 EndColor = vec4(0.0, 0.0, 0.0, 0.0);
 +
vec4 EndSpec  = vec4(0.0, 0.0, 0.0, 0.0);
 
for(int i = 0; i < LIGHT_COUNT; i++){
 
for(int i = 0; i < LIGHT_COUNT; i++){
 
vec3 Reflected = normalize(reflect(-lightvec[i], normal));  
 
vec3 Reflected = normalize(reflect(-lightvec[i], normal));  
Zeile 76: Zeile 80:
 
vec4 IDiffuse  = gl_LightSource[i].diffuse  * gl_FrontMaterial.diffuse  * max(dot(normal, lightvec[i]), 0.0);
 
vec4 IDiffuse  = gl_LightSource[i].diffuse  * gl_FrontMaterial.diffuse  * max(dot(normal, lightvec[i]), 0.0);
 
vec4 ISpecular = gl_LightSource[i].specular * gl_FrontMaterial.specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess);
 
vec4 ISpecular = gl_LightSource[i].specular * gl_FrontMaterial.specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess);
EndColor += (IAmbient+IDiffuse+ISpecular);
+
EndColor += (IAmbient+IDiffuse);
 +
EndSpec  += ISpecular;
 
}
 
}
 
EndColor += gl_FrontMaterial.emission;
 
EndColor += gl_FrontMaterial.emission;
  
gl_FragColor = (gl_FrontLightModelProduct.sceneColor + EndColor) * texture2D(Texture0, TexCoord);
+
gl_FragColor = (gl_FrontLightModelProduct.sceneColor + EndColor + EndSpec) * texture2D(Texture0, TexCoord);
 
}</source>
 
}</source>

Aktuelle Version vom 3. Januar 2014, 21:45 Uhr

Bumpmapping-Shader

Zurück zur Shadersammlung

Beschreibung Autor Version
per-Pixel-Beleuchtung unter Zuhilfenahme einer Normalmap um einen Bumpmapping Effekt zu erzeugen. Bergmann 1.0

Bilder

Die Originaltextur (Downloadvorlage)
Die Normalmap (Downloadvorlage)
Ergebnis

Beschreibung

Der Bumpmapping Shader basiert auf dem Per Pixel-Beleuchtung-Shader. Der Unterschied zu diesem besteht darin, das wir die Normale nicht einfach so benutzen, wie sie an den Shader übergeben wurde, sondern wir sie erst mit den Daten aus der NormalMap manipulieren müssen. Dazu basteln wir uns eine TBN Matrix aus der Sicht der Textur zusammen: x-Achse = Tangente, y-Achse = Bitangente und z-Achse = Normale.Die Berechnung der Vektoren erfolgt gemäß diesem Artikel.

Um weiter zu rechnen setzen wur nun die 3 Achsen zu einer Matrix zusammen:

mat3 M = mat3(T, B, N);


Um die Normale zu erzeugen, welche dann zur Lichtberechnung genutzt wird lesen wir zunächst die Daten aus der NormalMap. Da die Farbewerte immer im Bereich [0..1] liegen, eine Normale aber immer in alle Richtungen zeigen kann und nicht nur in die positiven, müssen wir von jedem Farbewert noch 0.5 abziehen und den Farbvektor dann normalisieren. Dann multiplizieren wir noch mit der zuvor erzeugten Matrix und der NormalMatrix:

vec3 normal = normalize((vec3(texture2D(Texture1, TexCoord)) - vec3(0.5, 0.5, 0.5)) * M);
normal = gl_NormalMatrix * normal;

Code

Vertexshader:

const int LIGHT_COUNT = 1;          //Anzahl der berücksichtigten Lichter
varying vec3 N;			    //NormalenVektor
varying vec3 V;			    //VertexVektor	
varying vec3 lightvec[LIGHT_COUNT]; //LichtVektor(en)
void main(void)
{
	gl_TexCoord[0]  = gl_MultiTexCoord0;
	N          	= normalize(gl_NormalMatrix * gl_Normal);
	V		= vec3(gl_ModelViewMatrix * gl_Vertex);
	for(int i = 0; i < LIGHT_COUNT; i++){
		lightvec[i] = normalize(gl_LightSource[i].position.xyz - V);
	}
	gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;
}


Fragmentshader:

const int LIGHT_COUNT = 1;
const float PI = 3.14159265;
varying vec3 N;
varying vec3 V;
varying vec3 lightvec[LIGHT_COUNT];
uniform sampler2D Texture0;
uniform sampler2D Texture1;

void main(void){
	vec2 TexCoord = vec2(gl_TexCoord[0]);
	vec3 Eye = normalize(-V); 

	vec3 q0 = dFdx(Eye.xyz);
	vec3 q1 = dFdy(Eye.xyz);
	vec2 st0 = dFdx(TexCoord.st);
	vec2 st1 = dFdy(TexCoord.st);
	
	vec3 S = normalize( q0 * st1.t - q1 * st0.t);
	vec3 T = normalize(-q0 * st1.s + q1 * st0.s);
	
	mat3 M = mat3(-T, -S, N);
	vec3 normal = normalize(M * (vec3(texture2D(Texture1, TexCoord)) - vec3(0.5, 0.5, 0.5)));
	
	vec4 EndColor = vec4(0.0, 0.0, 0.0, 0.0);
	vec4 EndSpec  = vec4(0.0, 0.0, 0.0, 0.0);
	for(int i = 0; i < LIGHT_COUNT; i++){
		vec3 Reflected = normalize(reflect(-lightvec[i], normal)); 
		vec4 IAmbient  = gl_LightSource[i].ambient  * gl_FrontMaterial.ambient;
		vec4 IDiffuse  = gl_LightSource[i].diffuse  * gl_FrontMaterial.diffuse  * max(dot(normal, lightvec[i]), 0.0);
		vec4 ISpecular = gl_LightSource[i].specular * gl_FrontMaterial.specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess);
		EndColor += (IAmbient+IDiffuse);
		EndSpec  += ISpecular;
	}
	EndColor += gl_FrontMaterial.emission;

	gl_FragColor = (gl_FrontLightModelProduct.sceneColor + EndColor + EndSpec) * texture2D(Texture0, TexCoord);
}