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; varying vec4 position; void main() { position= gl_vertex; float offset = ftime0_x *2.5; position.y= 0.2*sin(5.0*position.x+offset); Proměnná předávaná z aplikace čas aktuálního snímku gl_position= gl_modelviewprojectionmatrix*position; Přepočet geometrie 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); //intensity = max(dot(normalize(gl_lightsource[0].position.xyz),gl_normalmatrix*gl_normal),0.0); gl_position= gl_modelviewprojectionmatrix*gl_vertex; Výpočet difuzní složky ve vrcholech FS varying float intensity; void main() { vec4 color; if (intensity>0.95) else if (intensity>0.8) else if (intensity>0.5) else if (intensity>0.25) else gl_fragcolor = color; Skokové obarvení color=vec4(1.0,0.5,0.5,1.0); color=vec4(0.6,0.3,0.3,1.0); color=vec4(0.0,0.0,0.3,1.0); color=vec4(0.4,0.2,0.2,1.0); color=vec4(0.2,0.1,0.1,1.0); //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; void main() { float intensity; Výpočet difuzní složky per pixel na základě interpolované normály 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; ViewDirection = EyePosition - ObjectPosition.xyz; LightDirection = LightPosition - ObjectPosition.xyz; Normal = gl_normalmatrix * gl_normal; gl_position= gl_modelviewprojectionmatrix*gl_vertex; Pohledový vektor Vektor osvětlení Transformace normály
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 ); float NDotL = dot( Normal, LightDirection ); Difuzní složka 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 = normalize( LightDirection + ViewDirection); float NDotH = max( 0.0, dot( Normal, HalfVector ) ); vec4 TotalAmbient vec4 TotalDiffuse = Ambient * BaseColor; = Diffuse * NDotL * BaseColor; Specularní složka z HalfVectoru 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ý 1 f k k d k d c l q Výpočet vzdálenosti 2
VS uniform vec3 LightPosition; uniform vec3 EyePosition; varying vec3 ViewDirection; varying vec3 LightDirection; varying vec3 Normal; varying 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); gl_position= gl_modelviewprojectionmatrix*gl_vertex; Výpočet vzdálenosti od pozorovatele
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 ) ); float att=1.0/(constantattenuation+ Výpočet útlumu od zdroje světla 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; uniform vec3 spotdirection; void main( void ) {vec3 LightDirection = normalize( LightDirection ); vec3 Normal = normalize( Normal ); float NDotL = dot( Normal, LightDirection ); float spoteffect = dot(normalize(spotdirection),normalize(-lightdirection)); if (spoteffect>spotcutoff) { gl_fragcolor = att*( TotalAmbient + TotalDiffuse + TotalSpecular ); else gl_fragcolor = vec4(1.0,0.0,0.0,0.0); Osvětlení typu reflektor Výpočet osvětlení Mimo kužel světla Výpočet kuželu
Příklad - textura Tutor4-tex1 Mapování textury vec4 color=texture2d(te,gl_texcoord[0].st);
VS void main( void ) { gl_texcoord[0]=gl_multitexcoord0; //gl_texcoord[0].x=gl_multitexcoord0.x*4; gl_position=ftransform(); Přiřazení souřadnice do textury vrcholu Transformace souřadnic textury Transformace souřadnic vrcholu FS uniform sampler2d Texture0; uniform float ftime0_x; void main( void ) { vec4 color; 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); //gl_fragcolor.rgb=color.brr; gl_fragcolor.rgb=color.rgb; Odkaz na texturu (sampler) Souřadnice do textury Samplování vzorku (barvy) Obarvení pixelu
Příklad - textura Tutor4-tex2 Multitexturing a osvětlení +
VS FS uniform sampler2d Texture0; uniform sampler2d Texture1; void main( void ) { vec3 ct,cf; vec4 texel; Odkaz na texturu (sampler) cf=( TotalAmbient + TotalDiffuse + TotalSpecular).rgb; texel=texture2d(texture0,gl_texcoord[0].st); //texel=texture2d(texture1,texel.xy); Samplování vzorku (barvy) 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 P t t P 0 0;1 t 3 3P t 1 2 2 1 t 3P t 1 t P 1 t 2 Zvyšování dělení intervalu 1, 2, 3, 3 3
VS GS #version 330 layout(lines_adjacency) in; layout(line_strip, max_vertices = 104) out; uniform int times; in vec3 vcolor[]; out vec3 fcolor; vec3 p[4]; void main() { //počet deleni //vstupní a vystupni barva //ridici body 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]; for(int i=0; i<=times; i++) { 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); FS EmitVertex(); EndPrimitive(); Vstupem je linie a sousední body Výstupem line_strip Generování bodů Parametr řídící proměnná Ukončení geometrie
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