Programování shaderů GLSL
Příklad – vertex shader • Tutor1-Flat – Změna geometrie ve VS – Nastavení z podle hodnoty získané z aplikace – uniform App: loc=gl.glGetUniformLocation(sp,"fTime0_X"); gl.glUniform1f(loc,time); VS: uniform float fTime0_X;
VS uniform float fTime0_X; Proměnná předávaná z aplikace – čas aktuálního snímku varying vec4 position; void main() { position= gl_Vertex; float offset = fTime0_X *2.5; position.y= 0.2*sin(5.0*position.x+offset); Přepočet geometrie gl_Position= gl_ModelViewProjectionMatrix*position; }
FS varying vec4 position; void main() { gl_FragColor = vec4(vec3(position.x,position.y,position.z),1.0);
//gl_FragColor = gl_Color; }
Příklad • Tutor2-toon1 – Tónování – odstupňování odstínu podle NּL= cos úhlu – ve VS = interpolace barvy – Transformace normály! gl_NormalMatrix
VS varying float intensity; void main() { intensity = dot(vec3(0,0,1),gl_Normal); Výpočet difuzní složky ve vrcholech //intensity = max(dot(normalize(gl_LightSource[0].position.xyz),gl_NormalMatrix*gl_Normal),0 .0); gl_Position= gl_ModelViewProjectionMatrix*gl_Vertex; }
FS varying float intensity; void main() Skokové obarvení { vec4 color; if (intensity>0.95) color=vec4(1.0,0.5,0.5,1.0); else if (intensity>0.8) color=vec4(0.6,0.3,0.3,1.0); else if (intensity>0.5) color=vec4(0.0,0.0,0.3,1.0); else if (intensity>0.25) color=vec4(0.4,0.2,0.2,1.0); else color=vec4(0.2,0.1,0.1,1.0); gl_FragColor = color; //gl_FragColor = vec4( intensity, intensity, intensity, intensity); }
Příklad • Tutor2-toon2 – v FS = interpolace normály
VS varying vec3 normal; void main() { normal = gl_Normal; //normal = gl_NormalMatrix*gl_Normal; gl_Position= gl_ModelViewProjectionMatrix*gl_Vertex; } FS varying vec3 normal; Výpočet difuzní složky per pixel na void main() základě interpolované normály { float intensity; intensity = dot(normalize(gl_LightSource[0].position.xyz),(normal)); //intensity = dot(normalize(gl_LightSource[0].position.xyz),normalize(normal)); vec4 color=vec4(normal.yzx,1); if (intensity>0.95) color=vec4(1.0,0.5,0.5,1.0); else if (intensity>0.5) color=vec4(0.6,0.3,0.3,1.0); else if (intensity>0.25) color=vec4(0.4,0.2,0.2,1.0); else color=vec4(0.8,0.1,0.1,1.0); gl_FragColor = color; }
Příklad • Tutor2-toonFS – v FS = interpolace normály – Nutná normalizace!
Příklad na jiném tělese
Příklad • Tutor3-light1 – Difúzní osvětlení NdotL = max(dot(L,N),0) GL_ShadeModel FLAT_SHADE SMOOTH_SHADE
VS void main() { vec3 normal = gl_NormalMatrix*gl_Normal;
Transformace normály
Výpočet difuzní složky ve vrcholech float NdotL = max(dot(normalize(gl_LightSource[0].position.xyz),normalize(normal)),0); vec4 diffuse = gl_FrontMaterial.diffuse*gl_LightSource[0].diffuse; gl_FrontColor=NdotL*diffuse;
Nastavení standardní FrontColor
gl_Position= gl_ModelViewProjectionMatrix*gl_Vertex; }
FS void main() { gl_FragColor = gl_Color; }
Obarvení standardní barvou
Příklad • Tutor3-light2 – Blinn-Phong model osvětlení • Ambientní • Difúzní • Zrcadlová
– Výpočet HalfVektoru !
VS uniform vec3 LightPosition; uniform vec3 EyePosition;
varying vec3 ViewDirection; varying vec3 LightDirection; varying vec3 Normal; void main( void ) { vec4 ObjectPosition = gl_ModelViewMatrix * gl_Vertex;
Pohledový vektor ViewDirection = EyePosition - ObjectPosition.xyz; LightDirection = LightPosition - ObjectPosition.xyz; Vektor osvětlení Normal = gl_NormalMatrix * gl_Normal;
Transformace normály
gl_Position= gl_ModelViewProjectionMatrix*gl_Vertex; }
FS uniform vec4 Ambient,Specular,Diffuse,BaseColor; uniform float SpecularPower; varying vec3 ViewDirection,LightDirection,Normal; void main( void ) {vec3 LightDirection = normalize( LightDirection ); vec3 Normal = normalize( Normal ); Difuzní složka float NDotL = dot( Normal, LightDirection ); vec3 Reflection = normalize( ( ( 2.0 * Normal ) * NDotL )-LightDirection ); vec3 ViewDirection = normalize( ViewDirection ); Specularní složka float RDotV = max( 0.0, dot( Reflection, ViewDirection ) ); vec3 HalfVector float NDotH
= normalize( LightDirection + ViewDirection); = max( 0.0, dot( Normal, HalfVector ) );
Specularní složka z HalfVectoru vec4 TotalAmbient = Ambient * BaseColor; vec4 TotalDiffuse = Diffuse * NDotL * BaseColor; vec4 TotalSpecular = Specular * ( pow( NDotH, SpecularPower*4.0 ) ); // TotalSpecular = Specular * ( pow( RDotV, SpecularPower ) ); gl_FragColor = ( TotalAmbient + TotalDiffuse + TotalSpecular );
}
Příklad - útlum • Tutor3-light3 – Blinn-Phong model osvětlení – Útlum světla od zdroje – Koeficient útlumu • Konstantní • Lineární • Kvadratický f
1 k c kl d k q d 2
– Výpočet vzdálenosti
VS uniform vec3 LightPosition; uniform vec3 EyePosition;
varying varying varying varying
vec3 ViewDirection; vec3 LightDirection; vec3 Normal; float dist;
void main( void ) {
vec4 ObjectPosition = gl_ModelViewMatrix * gl_Vertex; ViewDirection = EyePosition - ObjectPosition.xyz; LightDirection = LightPosition - ObjectPosition.xyz; Normal = gl_NormalMatrix * gl_Normal; dist=length(ViewDirection); Výpočet vzdálenosti od pozorovatele gl_Position= gl_ModelViewProjectionMatrix*gl_Vertex; }
FS uniform vec4 Ambient,Specular,Diffuse,BaseColor; uniform float SpecularPower; varying vec3 ViewDirection,LightDirection,Normal; uniform float constantAttenuation, linearAttenuation, quadraticAttenuation; varying float dist; void main( void ) { vec3 LightDirection = normalize( LightDirection ); vec3 Normal = normalize( Normal ); float NDotL = dot( Normal, LightDirection ); vec3 ViewDirection = normalize( ViewDirection ); vec3 HalfVector = normalize( LightDirection + ViewDirection); float NDotH = max( 0.0, dot( Normal, HalfVector ) );
Výpočet útlumu od zdroje světla float att=1.0/(constantAttenuation+ linearAttenuation*dist+ quadraticAttenuation*dist*dist); vec4 TotalAmbient = Ambient * BaseColor; vec4 TotalDiffuse = Diffuse * NDotL * BaseColor; vec4 TotalSpecular = Specular * ( pow( NDotH, SpecularPower*4.0 ) ); gl_FragColor = att*( TotalAmbient + TotalDiffuse + TotalSpecular ); }
Příklad – reflektor • Tutor3-light4 – Blinn-Phong model osvětlení – Spot light • Úhel • Směr
FS uniform vec4 Ambient,Specular,Diffuse,BaseColor; uniform float SpecularPower; varying vec3 ViewDirection,LightDirection,Normal; uniform float constantAttenuation, linearAttenuation, quadraticAttenuation; varying float dist; uniform float spotCutOff; Osvětlení typu reflektor uniform vec3 spotDirection; void main( void ) {vec3 LightDirection = normalize( LightDirection ); vec3 Normal = normalize( Normal ); float NDotL = dot( Normal, LightDirection ); Výpočet kuželu float spotEffect = dot(normalize(spotDirection),normalize(-LightDirection)); if (spotEffect>spotCutOff) { … Výpočet osvětlení gl_FragColor = att*( TotalAmbient + TotalDiffuse + TotalSpecular ); } else gl_FragColor = vec4(1.0,0.0,0.0,0.0); Mimo kužel světla }
Příklad - textura • Tutor4-tex1 – Mapování textury vec4 color=texture2D(te,gl_TexCoord[0].st);
VS Přiřazení souřadnice do textury vrcholu void main( void ) { gl_TexCoord[0]=gl_MultiTexCoord0; //gl_TexCoord[0].x=gl_MultiTexCoord0.x*4; Transformace souřadnic textury gl_Position=ftransform(); Transformace souřadnic vrcholu } FS uniform sampler2D Texture0; Odkaz na texturu (sampler) uniform float fTime0_X; void main( void ) { vec4 color; Souřadnice do textury vec2 st=gl_TexCoord[0].st; //st.s=sqrt(st.s)*4.0; //st.t=st.t+cos(st.s*10)/10; //st.t= 0.2*sin(5.0*st.t+fTime0_X *2.5); color=texture2D(Texture0,st); Samplování vzorku (barvy) //gl_FragColor.rgb=color.brr; Obarvení pixelu gl_FragColor.rgb=color.rgb; }
Příklad - textura • Tutor4-tex2 – Multitexturing a osvětlení
+
VS …
FS … Odkaz na texturu (sampler) uniform sampler2D Texture0; uniform sampler2D Texture1; void main( void ) { … vec3 ct,cf; vec4 texel; cf=( TotalAmbient + TotalDiffuse + TotalSpecular).rgb; texel=texture2D(Texture0,gl_TexCoord[0].st); Samplování vzorku (barvy) //texel=texture2D(Texture1,texel.xy);
Transformace texturou
//texel=texture2D(Texture0,gl_TexCoord[0].st) +texture2D(Texture1,gl_TexCoord[0].st); Samplování vzorku (barvy)
ct=texel.rgb; gl_FragColor=vec4(cf*ct,0);}
}
Složení textury a osvětlení Obarvení pixelu
Příklad – Geometry shader • Generování dalších vrcholů aproximační křivky - Bézier • Bod na křivce Pt P0 t 3 3P1t 2 1 t 3P2 t 1 t P3 1 t 2
3
t 0;1
• Zvyšování dělení intervalu 1, 2, 3, …
VS … GS Vstupem je linie a sousední body #version 330 Výstupem line_strip layout(lines_adjacency) in; layout(line_strip, max_vertices = 104) out; uniform int times; //počet deleni in vec3 vColor[]; out vec3 fColor; //vstupní a vystupni barva vec3 p[4]; //ridici body void main() { p[0]=gl_in[0].gl_Position.xyz*0.5+gl_in[1].gl_Position.xyz*0.5; p[1]=gl_in[1].gl_Position.xyz; p[2]=gl_in[2].gl_Position.xyz; p[3]=gl_in[2].gl_Position.xyz*0.5+gl_in[3].gl_Position.xyz*0.5; fColor = vColor[0]; Generování bodů for(int i=0; i<=times; i++) { Parametr – řídící proměnná float t=1-i*1.0/times; gl_Position = vec4(p[0]*t*t*t + p[1]*t*(1-t)*3*t + p[2]*3*t*(1-t)*(1-t) + p[3]*(1-t)*(1-t)*(1-t),1); EmitVertex(); } Ukončení geometrie EndPrimitive(); } FS …
Ladění • Obtížné – nelze jednoduše trasovat ani vypisovat • Výpis stavu compilace VS a FS glGetObjectParameterivARB glGetInfoLogARB
• Od verze 2.0 glGetShaderInfoLog – Výpis stavu compilace VS nebo FS glGetProgramInfoLog – Výpis stavu linkování VS a FS do shader programu
Ladění • Použití standardní výstupů – VS: gl_Position+=1.0; – FS: gl_FragColor.rgb=normal;
• Používat jednoduchou geometrii – trojúhelník, quad…
• Jednoduché (jednotkové) matice – gl_ViewMatrix, gl_ProjectionMatrix
Ladění - nástroje • • • •
Shader Designer Shader Gen Render Monkey gDEBugger
• GLIntercept, • imdebug
Další nástroje • http://web.engr.oregonstate.edu/~mjb/glman/ • http://www.malideveloper.com/developer-resources/tools/shaderdevelopment-studio.php • http://www.imgtec.com/powervr/insider/powervr-pvrshaman.asp • http://cg.in.tu-clausthal.de/teaching/shader_maker/index.shtml • http://sourceforge.net/projects/lumina/ • http://qt.digia.com/product/developer-tools/ • http://www.iquilezles.org/apps/shadertoy/ • http://www.kickjs.org/example/shader_editor/shader_editor.html • http://code.google.com/p/renderhog/ • http://glslstudio.com/
Shader Gen
Render Monkey
gDEBugger
Kick – WWW IDE • http://www.kickjs.org/example/shader_editor/shader_editor.html
Shader Toy – WWW IDE • https://www.shadertoy.com