[FTEQW][REL]GLSL showreel - also mini tutorial
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
[FTEQW][REL]GLSL showreel - also mini tutorial
When I was creating the skeleton of the project I asked myself: "What if I create a project without neither models, maps, nor textures, just procedural models and GLSL shaders?"
The idea behind this GLSL showreel is double face: the project (that lives in this page, with no additional physical contents, except for sounds files) and a mini-tutorial that explains how GLSL shaders and postprocessing are possible with FTE engine. Yeah, I know, mini-tutorial part is a bit lame, but, for now, it's the maximum I can do. If you have any input to share, please post it below and I'll add it with your credits
This is the video showing the final project. It's not wonderful but I liked it for many reasons, first of all is that, for creating it, you'll need just the pieces of code I'll write in this topic: that's it, no 3d models, no textures, no maps! Crazy, isn't it? Well, let's see..
CSQC Warning: this mini-tutorial requires basic/mid knowledge of CSQC to understand it (otherwise you can just follow the steps and obtain the final project anyway, but that's half of the fun imo..)
a
License warning: GLSL showreel code is 100% written by me (Antonio Latronico) and placed under cc0 public domain license, so you can do basically what you want with it without any kind of restrictions, BUT (and this is very important) every GLSL file present in this mini-tutorial is not written by me (I downloaded from shadertoy and "just" adapted to FTEism GLSL syntax), so you MUST pay attention to every GLSL file license header to be sure to credit every single author to avoid license infringement (unfortunately, 70% of GLSL files are released under CC non commercial license, so, forget about using those files for commercial projects..ugh..)
Nomenclature warning: When I talk about a shader, I describe .shader files stored in scripts subfolder in game data folder, when I talk about a GLSL file I mean glsl files in glsl subfolder in game data folder
GLSL files external licenses:
Overcast Sky
author: CaliCoastReplay
https://www.shadertoy.com/view/Ml3Gzs
Warp Speed
author: David Hoskins 2013.
https://www.shadertoy.com/view/Msl3WH#
Synthetic aperture
author: FabriceNeyret2
https://www.shadertoy.com/view/ldlSzX#
Tileable Water Caustic
author: David Hoskins
https://www.shadertoy.com/view/MdlXz8
Post Processing effect: ASCII
author: mattdesl
https://www.npmjs.com/package/glsl-asci ... -pixelsize
Post Processing effect: Black&White
author: lezard
https://blog.sovapps.com/play-with-shad ... te-part-1/
Post Processing effect: Bloom
author: mAlk
https://www.shadertoy.com/view/Ms2Xz3
Post Processing effect: Barrel Blur Chroma
author: hornet
https://www.shadertoy.com/view/XssGz8
Post Processing effect: Fast, Small-Radius GPU Median Filter
author: Morgan McGuire
http://graphics.cs.williams.edu/papers/MedianShaderX6/
Post Processing effect: GLSL depth of field (used as Motion Blur)
author: martins upitis
http://devlog-martinsh.blogspot.it/2011 ... eh-v2.html
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
Step-by-step reel creation:
- Grab from here latest version of FTEQW for your O.S. (I'd suggest debug version, for better debugging, but it's up to you)
- Create in main game folder a textfile named default.fmf and edit like this
Code: Select all
game gs name "GLSL Showreel" basegame data disablehomedir 1
- Create a data folder, inside create 2 subfolders: glsl and scripts
- In scripts folder create a text file named objects.shader (this will store shaders for objects in scene) and edit like this
Code: Select all
sky { program ton_daysky cull none } sea { program ton_sea cull none } portal { program ton_portal cull none } portal2 { program ton_portal2 cull none } portalframe { program ton_portalframe cull none } portalframe2 { program ton_portalframe2 cull none } horizon { program ton_flatcolor#AZURE cull none } cube { program ton_flatcolor#GREYDARK cull none }
- In scripts folder create a text file named pp.shader (this will store shaders for post-processing effects) and edit like this:
Code: Select all
ppcolor { program ton_pp_basic { map $rt:ppcolor } { map $sourcedepth } } ppdepth { program ton_pp_depth { map $rt:ppdepth } { map $sourcedepth } } ppbandw { program ton_pp_bandw { map $rt:ppbandw } } ppmblur { program ton_pp_motionblur { map $rt:ppmblur } } ppchrom { program ton_pp_chromaticaberration { map $rt:ppchrom } } ppascii { program ton_pp_ascii { map $rt:ppascii } } ppbloom { program ton_pp_bloom { map $rt:ppbloom } } ppmedian { program ton_pp_median { map $rt:ppmedian } }
- In glsl folder let's add all the glsl files that will be called by shaders. Let's start with the ones called by objects.shader. Remember to add to every glsl file a .glsl extension and remember to contact glsl file author before using it in your commercial project!
ton_daysky.glslton_flatcolor.glslCode: Select all
!!ver 330 !!cvarf glsl_time !!cvarf glsl_skysize !!permu FOG // author: CaliCoastReplay // https://www.shadertoy.com/view/Ml3Gzs // Adapted from : https://www.shadertoy.com/view/Md3SzB #include "sys/fog.h" #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform float cvar_glsl_time;//time set in a cvar!! uniform float cvar_glsl_skysize; vec3 rgb2hsv(vec3 c) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); float d = q.x - min(q.w, q.y); float e = 1.0e-10; return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); } vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } float hash21(vec2 p) { float h = dot(p,vec2(127.1,311.7)); return -1.+2.*fract(sin(h)*43758.5453123); } vec2 hash22(vec2 p) { p = p*mat2(127.1,311.7,269.5,183.3); p = -1.0 + 2.0 * fract(sin(p)*43758.5453123); return sin(p*6.283 + cvar_glsl_time/4.0); } float perlin_noise(vec2 p) { vec2 pi = floor(p); vec2 pf = p-pi; vec2 w = pf*pf*(3.-2.*pf); float f00 = dot(hash22(pi+vec2(.0,.0)),pf-vec2(.0,.0)); float f01 = dot(hash22(pi+vec2(.0,1.)),pf-vec2(.0,1.)); float f10 = dot(hash22(pi+vec2(1.0,0.)),pf-vec2(1.0,0.)); float f11 = dot(hash22(pi+vec2(1.0,1.)),pf-vec2(1.0,1.)); float xm1 = mix(f00,f10,w.x); float xm2 = mix(f01,f11,w.x); float ym = mix(xm1,xm2,w.y); return ym; } float noise(vec2 p) { p *= 4.; float a = 1., r = 0., s=0.; for (int i=0; i<9; i++) { r += a*perlin_noise(p); s+= a; p *= 2.00; a*=.57; } return r/s;///(.1*3.); } vec3 sphereProject(vec2 plane) { vec3 r; plane.x -= 0.55; plane.y -= 0.35; float denom = (1.0 + plane.x*plane.x + plane.y*plane.y); r.x = (2.0*plane.x)/denom; r.y = (2.0*plane.y)/denom; r.z = (1.0 - plane.x*plane.x+plane.y*plane.y)/denom; return r*1.2; } void main( void ) { vec2 uv = v_edge.xy / cvar_glsl_skysize * 0.6; //vec3 sphere = sphereProject(uv); //uv = sphere.xy/2.1; vec2 uv2 = uv + vec2(0.12253 + cvar_glsl_time/210.0,0.73483-cvar_glsl_time/90.3); vec2 uv3 = uv + vec2(0.34646 - cvar_glsl_time/150.3,0.46436 - cvar_glsl_time/180.4); vec2 uv4 = uv + vec2(0.98398 - cvar_glsl_time/34.5,0.11242 + cvar_glsl_time/100.7); float f = noise(uv)/1.0; f+= noise(uv3)/2.45; f+= noise(uv4)/0.7; f = f*0.35+0.55; vec3 lightColor = vec3(0.719,0.719,1.0); vec3 color = vec3(lightColor*f); vec3 hsv = rgb2hsv(color); hsv.z += 0.5; float cloudCoverFactor = 0.01; hsv.z *= hsv.z * hsv.z * sqrt(hsv.z)* 2.01 * (cloudCoverFactor + 0.91); bool deblue = false; if (hsv.z > 2.75) { hsv.z =4.7 - hsv.z/2.11; hsv.z -= 0.559; deblue = true; } else{ hsv.z -= 0.041; } hsv.y *= 2.2; hsv.z -= 0.01; color = hsv2rgb(hsv); if (deblue){ color.z = color.y = color.x * .91; color.x -= 0.07; } gl_FragColor = vec4(color,1.0); #ifdef FOG gl_FragColor = fog4(gl_FragColor); #endif } #endif
ton_portal.glslCode: Select all
!!ver 330 //author: Antonio "toneddu2000" Latronico //placed under cc0 public domain license #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER void main() { gl_FragColor = vec4(vec3(0,0,1),1.0); #ifdef GREENLIGHT gl_FragColor = vec4(vec3(0.248,0.840,0.293),1.0); #endif #ifdef GREENDARK gl_FragColor = vec4(vec3(0.115,0.390,0.136),1.0); #endif #ifdef AZURE gl_FragColor = vec4(vec3(0.666,0.823,0.912),1.0); #endif #ifdef RED gl_FragColor = vec4(vec3(0.910,0.081,0.116),1.0); #endif #ifdef WHITE gl_FragColor = vec4(vec3(1,1,1),1.0); #endif #ifdef GREYDARK gl_FragColor = vec4(vec3(0.330,0.340,0.340),1.0); #endif } #endif
ton_portal2.glslCode: Select all
!!ver 330 !!cvarf glsl_time !!permu FOG #include "sys/fog.h" // 'Warp Speed' // author: David Hoskins 2013. // https://www.shadertoy.com/view/Msl3WH# #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform float cvar_glsl_time; #define TAU 6.28318530718 #define MAX_ITER 5 void main( void ) { float time = (cvar_glsl_time+29.) * 60.0; float s = 0.0, v = 0.0; vec2 uv = (v_edge.xy) * 2.0 - 1.0; float t = time*0.005; uv.x = (uv.x) + sin(t) * 0.5; float si = sin(t + 2.17); // ...Squiffy rotation matrix! float co = cos(t); uv *= mat2(co, si, -si, co); vec3 col = vec3(0.0); vec3 init = vec3(0.25, 0.25 + sin(time * 0.001) * 0.4, floor(time) * 0.0008); for (int r = 0; r < 100; r++) { vec3 p = init + s * vec3(uv, 0.143); p.z = mod(p.z, 2.0); for (int i=0; i < 10; i++) p = abs(p * 2.04) / dot(p, p) - 0.75; v += length(p * p) * smoothstep(0.0, 0.5, 0.9 - s) * .002; // Get a purple and cyan effect by biasing the RGB in different ways... col += vec3(v * 0.8, 1.1 - s * 0.5, .7 + v * 0.5) * v * 0.013; s += .01; } gl_FragColor = vec4(col, 1.0); #ifdef FOG gl_FragColor = fog4(gl_FragColor); #endif } #endif
ton_portalframe.glslCode: Select all
!!ver 330 !!cvarf glsl_time !!permu FOG // author: FabriceNeyret2 // https://www.shadertoy.com/view/ldlSzX# #include "sys/fog.h" #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform float cvar_glsl_time; #define N 23 // number of sources int MODE = 5; // source distrib float POW = 1.; // fading with distance const float k = 2.*3.14159/.04, // 2 Pi / wavelenght c = 0.1; // wavespeed #define t cvar_glsl_time bool keyToggle(int ascii) { return (vec3(0,vec2((.5+float(ascii))/256.,0.75)).x > 0.); } float rnd(float i) { return mod(4000.*sin(23464.345*i+45.345),1.); } float srnd(float i) { return 2.*rnd(i)-1.; } void main(void) { vec2 uv = 2.*(v_edge.xy-vec2(.5,.5)); // --- controls vec2 mouse = vec2(1.5*cos(.2345*t)-.7*sin(t),sin(.3214*t)+.5*cos(1.234*t))/1.5; bool DISPLAY = keyToggle(64+23); // waves vs energy bool RND = keyToggle(64+18); // even vs random source distrib MODE = ( (keyToggle(32)||keyToggle(64+19)) ? 1 : 3 ) + ( (RND) ?0:1); // line or circle source POW = (keyToggle(64+16)) ? 0. : 1.; // 1/r decrease or not // --- calc sources contribs float x = -.75, y=-.7, xt = x +((keyToggle(64+20))?.03*t:0.); const float step = 1.54/float(N); float Phi[N],D2[N]; for (int i=0; i<N; i++) { vec2 P; // generates sources distribution if (MODE==1) { P = vec2(x,-.9); x+= step;} else if (MODE==2) { P = vec2(x,-.9); x+= step*(1.+srnd(float(i))); } else if (MODE==3) { P = .99*vec2(sin(4.*xt),-cos(4.*xt)); xt+= step;} else if (MODE==4) { P = .99*vec2(sin(4.*xt),-cos(4.*xt)); xt+= step*(1.+.7*srnd(float(i)));} else if (MODE==5) { P = vec2(2.*x,y); x+= 1.4*sqrt(step); if (x>.7) { x=-.7; y+=sqrt(1.4*step);} } // the key: wave's phase pixel to source calibrated by wave phase mouse to source float dm = length(mouse-P), phim = dm, // -c*t, d = length(uv-P), phi = d -c*t; Phi[i] = k*(phi-phim); // stores wave attributes D2[i] = pow(d,POW); if (d<0.01) { gl_FragColor = vec4(0.,0.,1.,0.); return; } } // --- combines waves or energy float v = 0.; if (DISPLAY) // waves for (int i=0; i<N; i++) v += cos(Phi[i])/D2[i]; else { // energy . is int_t{ ( sum_i{waves(i,x,t)} )^2 } #if 1 for (int i=0; i<N; i++) { for (int j=0; j<N; j++) v += cos(Phi[j]-Phi[i]) / (D2[i]*D2[j]); // if (j<i) v += 2.*cos(Phi[j]-Phi[i]) / (D2[i]*D2[j]); // not faster ! //v += 1./ (D2[i]*D2[i]); } #else for (int i=0; i<N; i++) v += 1./ (D2[i]*D2[i]); int i=0, j=N-1; for (int k=0; k<N*(N-1)/2; k++) { if (i>=j) { i=0; j--; } v += 2.*cos(Phi[j]-Phi[i]) / (D2[i]*D2[j]); } #endif v = sqrt(v/2.); } v = v*4.5/float(N); gl_FragColor = vec4(v,v/2.,v/4.,1.); #ifdef FOG gl_FragColor = fog4(gl_FragColor); #endif } #endif
ton_portalframe2.glslCode: Select all
!!ver 330 !!cvarf glsl_time // author: Antonio "toneddu2000" Latronico // placed under cc0 public domain license #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform float cvar_glsl_time;//time set in a cvar!! vec3 start = vec3(0.489,0.650,0.912); vec3 end = vec3(0.624,0.893,1.000); void main() { vec3 color = vec3(0.0); color = mix(start, end, abs(sin(cvar_glsl_time))); gl_FragColor = vec4(color,1.0); } #endif
ton_sea.glslCode: Select all
!!ver 330 !!cvarf glsl_time // author: Antonio "toneddu2000" Latronico // placed under cc0 public domain license #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform float cvar_glsl_time;//time set in a cvar!! vec3 start = vec3(0.912,0.161,0.003); vec3 end = vec3(1.000,0.697,0.139); void main() { vec3 color = vec3(0.0); color = mix(start, end, abs(sin(cvar_glsl_time))); gl_FragColor = vec4(color,1.0); } #endif
Code: Select all
!!ver 330 !!cvarf glsl_time !!cvarf glsl_seasize !!permu FOG // author: David Hoskins. // https://www.shadertoy.com/view/MdlXz8 // Water turbulence effect by joltz0r 2013-07-04, improved 2013-07-07 #include "sys/fog.h" #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform float cvar_glsl_time; uniform float cvar_glsl_seasize; #define TAU 6.28318530718 #define MAX_ITER 5 void main( void ) { float time = cvar_glsl_time * .5+23.0; vec2 texres = vec2(cvar_glsl_seasize,cvar_glsl_seasize); // uv should be the 0-1 uv of texture... vec2 uv = v_edge.xy / texres.xy; vec2 p = mod(uv*TAU, TAU)-250.0; vec2 i = vec2(p); float c = 1.0; float inten = .005; for (int n = 0; n < MAX_ITER; n++) { float t = time * (1.0 - (3.5 / float(n+1))); i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x)); c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten))); } c /= float(MAX_ITER); c = 1.17-pow(c, 1.4); vec3 colour = vec3(pow(abs(c), 8.0)); colour = clamp(colour + vec3(0.0, 0.35, 0.5), 0.0, 1.0); gl_FragColor = vec4(colour, 1.0); #ifdef FOG gl_FragColor = fog4(gl_FragColor); #endif } #endif
- Now let's create, in the same glsl folder, all the glsl files for post processing effects
ton_pp_ascii.glslton_pp_bandw.glslCode: Select all
!!ver 130 // author: mattdesl // https://www.npmjs.com/package/glsl-ascii-filter#float-asciifilter-vec3-color-vec2-uv-float-pixelsize // A simple ASCII post-processing effect in GLSL, original at https://www.shadertoy.com/view/lssGDj by @movAX13h. #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main () { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER uniform sampler2D s_t0; uniform vec3 iResolution; varying vec2 v_edge; float character(float n, vec2 p) { p = floor(p*vec2(4.0, -4.0) + 2.5); if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y){ if (int(mod(n/exp2(p.x + 5.0*p.y), 2.0)) == 1) return 1.0; } return 0.0; } float luma(vec3 color) { return dot(color, vec3(0.299, 0.587, 0.114)); } float asciiFilter(vec3 color, vec2 uv, float pixelSize) { float threshold = luma(color); float n = 65536.0; // . if (threshold > 0.2) n = 65600.0; // : if (threshold > 0.3) n = 332772.0; // * if (threshold > 0.4) n = 15255086.0; // o if (threshold > 0.5) n = 23385164.0; // & if (threshold > 0.6) n = 15252014.0; // 8 if (threshold > 0.7) n = 13199452.0; // @ if (threshold > 0.8) n = 11512810.0; // # vec2 p = mod( uv / ( pixelSize * 0.2 ), 2.0) - vec2(1.0); return character(n, p); } float asciiFilter(vec3 color, vec2 uv) { return asciiFilter(color, uv, 1.0 / 25.0); } void main () { vec4 color = texture2D(s_t0, v_edge.xy); //aspect-corrected screen UVs vec2 st = v_edge.xy; //st.x *= iResolution.x / iResolution.y; //st.x = iResolution.x * 2; //apply filter //gl_FragColor.rgb = color.rgb * asciiFilter(color.rgb, st); //gl_FragColor.a = color.a; vec4 zaz; zaz.rgb = color.rgb * asciiFilter(color.rgb, st); gl_FragColor = vec4(zaz.r, zaz.g, zaz.b, 1); } #endif
ton_pp_basic.glslCode: Select all
!!ver 130 // author: lezard //https://blog.sovapps.com/author/lezard/ // https://blog.sovapps.com/play-with-shaders-black-and-white-part-1/ #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main () { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER uniform sampler2D s_t0; varying vec2 v_edge; varying vec3 graycol; uniform vec4 tint = vec4(1,1,1,1); void main () { gl_FragColor = texture2D(s_t0, v_edge.xy); vec4 normalColor = texture2D(s_t0, v_edge.xy); float gray = 0.299*normalColor.r + 0.587*normalColor.g + 0.114*normalColor.b; gl_FragColor = vec4(gray, gray, gray, normalColor.a); } #endif
ton_pp_bloom.glslCode: Select all
!!ver 330 // author: Antonio "toneddu2000" Latronico // placed under cc0 public domain license #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform sampler2D s_t0; void main(void) { vec3 img; img = vec3(texture2D(s_t0,v_edge.xy)); gl_FragColor = vec4(vec3(img.r,img.g,img.b),1); } #endif
ton_pp_chromaticaberration.glslCode: Select all
!!ver 330 !!cvarf glsl_bloomthres !!cvarf glsl_bloomintensity // author: mAlk // https://www.shadertoy.com/view/Ms2Xz3 #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform sampler2D s_t0; uniform float cvar_glsl_bloomthres; uniform float cvar_glsl_bloomintensity; vec4 BlurColor (in vec2 Coord, in sampler2D Tex, in float MipBias) { vec2 res = vec2(0.5,0.5); vec2 TexelSize = MipBias/res.xy; vec4 Color = texture(Tex, Coord, MipBias); Color += texture(Tex, Coord + vec2(TexelSize.x,0.0), MipBias); Color += texture(Tex, Coord + vec2(-TexelSize.x,0.0), MipBias); Color += texture(Tex, Coord + vec2(0.0,TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(0.0,-TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(TexelSize.x,TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(-TexelSize.x,TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(TexelSize.x,-TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(-TexelSize.x,-TexelSize.y), MipBias); return Color/9.0; } void main() { float thres = cvar_glsl_bloomthres; float intens = cvar_glsl_bloomintensity; float blursize = 0.5; vec2 uv = (v_edge.xy); vec4 Color = texture(s_t0, uv); vec4 highlight = clamp(BlurColor(uv, s_t0, blursize)-thres,0.0,1.0)*1.0/(1.0-thres); gl_FragColor = 1.0-(1.0-Color)*(1.0-highlight*intens); //Screen Blend Mode } #endif
ton_pp_depth.glslCode: Select all
!!ver 330 // author: hornet // https://www.shadertoy.com/view/XssGz8 #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); //gl_TexCoord[0] = gl_MultiTexCoord0; v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform sampler2D s_t0; float linterp( float t ) { return clamp( 1.0 - abs( 2.0*t - 1.0 ), 0.0, 1.0 ); } float remap( float t, float a, float b ) { return clamp( (t - a) / (b - a), 0.0, 1.0 ); } vec2 remap( vec2 t, vec2 a, vec2 b ) { return clamp( (t - a) / (b - a), 0.0, 1.0 ); } vec3 spectrum_offset_rgb( float t ) { vec3 ret; float lo = step(t,0.5); float hi = 1.0-lo; float w = linterp( remap( t, 1.0/6.0, 5.0/6.0 ) ); ret = vec3(lo,1.0,hi) * vec3(1.0-w, w, 1.0-w); return pow( ret, vec3(1.0/2.2) ); } const float gamma = 2.2; vec3 lin2srgb( vec3 c ) { return pow( c, vec3(gamma) ); } vec3 srgb2lin( vec3 c ) { return pow( c, vec3(1.0/gamma)); } vec3 yCgCo2rgb(vec3 ycc) { float R = ycc.x - ycc.y + ycc.z; float G = ycc.x + ycc.y; float B = ycc.x - ycc.y - ycc.z; return vec3(R,G,B); } vec3 spectrum_offset_ycgco( float t ) { //vec3 ygo = vec3( 1.0, 1.5*t, 0.0 ); //green-pink //vec3 ygo = vec3( 1.0, -1.5*t, 0.0 ); //green-purple vec3 ygo = vec3( 1.0, 0.0, -1.25*t ); //cyan-orange //vec3 ygo = vec3( 1.0, 0.0, 1.5*t ); //brownyello-blue return yCgCo2rgb( ygo ); } vec3 yuv2rgb( vec3 yuv ) { vec3 rgb; rgb.r = yuv.x + yuv.z * 1.13983; rgb.g = yuv.x + dot( vec2(-0.39465, -0.58060), yuv.yz ); rgb.b = yuv.x + yuv.y * 2.03211; return rgb; } // ==== //note: from https://www.shadertoy.com/view/XslGz8 vec2 radialdistort(vec2 coord, vec2 amt) { vec2 cc = coord - 0.5; return coord + 2.0 * cc * amt; } // Given a vec2 in [-1,+1], generate a texture coord in [0,+1] vec2 barrelDistortion( vec2 p, vec2 amt ) { p = 2.0 * p - 1.0; /* const float maxBarrelPower = 5.0; //note: http://glsl.heroku.com/e#3290.7 , copied from Little Grasshopper float theta = atan(p.y, p.x); vec2 radius = vec2( length(p) ); radius = pow(radius, 1.0 + maxBarrelPower * amt); p.x = radius.x * cos(theta); p.y = radius.y * sin(theta); /*/ // much faster version //const float maxBarrelPower = 5.0; //float radius = length(p); const float maxBarrelPower = sqrt(5.0); float radius = dot(p,p); //faster but doesn't match above accurately p *= pow(vec2(radius), maxBarrelPower * amt); /* */ return p * 0.5 + 0.5; } //note: from https://www.shadertoy.com/view/MlSXR3 vec2 brownConradyDistortion(vec2 uv, float dist) { uv = uv * 2.0 - 1.0; // positive values of K1 give barrel distortion, negative give pincushion float barrelDistortion1 = 0.1 * dist; // K1 in text books float barrelDistortion2 = -0.025 * dist; // K2 in text books float r2 = dot(uv,uv); uv *= 1.0 + barrelDistortion1 * r2 + barrelDistortion2 * r2 * r2; //uv *= 1.0 + barrelDistortion1 * r2; // tangential distortion (due to off center lens elements) // is not modeled in this function, but if it was, the terms would go here return uv * 0.5 + 0.5; } vec2 distort( vec2 uv, float t, vec2 min_distort, vec2 max_distort ) { vec2 dist = mix( min_distort, max_distort, t ); //return radialdistort( uv, 2.0 * dist ); //return barrelDistortion( uv, 1.75 * dist ); //distortion at center return brownConradyDistortion( uv, 75.0 * dist.x ); } // ==== vec3 spectrum_offset_yuv( float t ) { //vec3 yuv = vec3( 1.0, 3.0*t, 0.0 ); //purple-green //vec3 yuv = vec3( 1.0, 0.0, 2.0*t ); //purple-green vec3 yuv = vec3( 1.0, 0.0, -1.0*t ); //cyan-orange //vec3 yuv = vec3( 1.0, -0.75*t, 0.0 ); //brownyello-blue return yuv2rgb( yuv ); } vec3 spectrum_offset( float t ) { return spectrum_offset_rgb( t ); //return spectrum_offset_ycgco( t ); //return spectrum_offset_yuv( t ); } // ==== float nrand( vec2 n ) { return fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453); } void main( ) { vec2 uv = v_edge.xy; //tweak these 2 const const float MAX_DIST_PX = 40.0; const float SIZE = 3; float max_distort_px = MAX_DIST_PX * (1.0-vec2(0.5,0.8).x/1920); vec2 max_distort = vec2(max_distort_px) / vec2(1920,1080); vec2 min_distort = SIZE * max_distort; //vec2 oversiz = vec2(1.0); vec2 oversiz = distort( vec2(1.0), 1.0, min_distort, max_distort ); uv = remap( uv, 1.0-oversiz, oversiz ); //debug oversiz //vec2 distuv = distort( uv, 1.0, max_distort ); //if ( abs(distuv.x-0.5)>0.5 || abs(distuv.y-0.5)>0.5) //{ // fragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); return; //} vec3 sumcol = vec3(0.0); vec3 sumw = vec3(0.0); float rnd = nrand( uv + fract(0.01) ); const int num_iter = 16; for ( int i=0; i<num_iter;++i ) { float t = (float(i)+rnd) / float(num_iter-1); vec3 w = spectrum_offset( t ); sumw += w; sumcol += w * srgb2lin(texture2D( s_t0, distort(uv, t, min_distort, max_distort ) ).rgb); } sumcol.rgb /= sumw; vec3 outcol = lin2srgb(sumcol.rgb); outcol += rnd/255.0; gl_FragColor = vec4( outcol, 1.0); } #endif
ton_pp_median.glslCode: Select all
!!ver 330 // author: Antonio "toneddu2000" Latronico // placed under cc0 public domain license #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform sampler2D s_t0; void main(void) { vec3 img; img = vec3(texture2D(s_t0,v_edge.xy)); gl_FragColor = vec4(img,1); } #endif
ton_pp_motionblur.glslCode: Select all
!!ver 330 // author: Morgan McGuire https://www.cs.williams.edu/~morgan/ // http://graphics.cs.williams.edu/papers/MedianShaderX6/ #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); //gl_TexCoord[0] = gl_MultiTexCoord0; v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER uniform sampler2D s_t0; varying vec2 v_edge; #ifndef G3D // vec2(1/width, 1/height) of the texture uniform vec2 Tinvsize; #else # define Tinvsize g3d_sampler2DInvSize(s_t0)) #endif // Change these 2 defines to change precision, #define vec vec3 #define toVec(x) x.rgb //#define vec vec4 //#define toVec(x) x.rgba #define s2(a, b) temp = a; a = min(a, b); b = max(temp, b); #define mn3(a, b, c) s2(a, b); s2(a, c); #define mx3(a, b, c) s2(b, c); s2(a, c); #define mnmx3(a, b, c) mx3(a, b, c); s2(a, b); // 3 exchanges #define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d); // 4 exchanges #define mnmx5(a, b, c, d, e) s2(a, b); s2(c, d); mn3(a, c, e); mx3(b, d, e); // 6 exchanges #define mnmx6(a, b, c, d, e, f) s2(a, d); s2(b, e); s2(c, f); mn3(a, b, c); mx3(d, e, f); // 7 exchanges void main() { vec v[9]; //change noise1 to increase / decrease float noise1 = 0.003; // Add the pixels which make up our window to the pixel array. for(int dX = -1; dX <= 1; ++dX) { for(int dY = -1; dY <= 1; ++dY) { vec2 offset = vec2(float(dX), float(dY)); // If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) + (dY + R) of the // pixel array. This will fill the pixel array, with the top left pixel of the window at pixel[0] and the // bottom right pixel of the window at pixel[N-1]. v[(dX + 1) * 3 + (dY + 1)] = toVec(texture2D(s_t0, v_edge.xy + offset * noise1)); } } vec temp; // Starting with a subset of size 6, remove the min and max each time mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]); mnmx5(v[1], v[2], v[3], v[4], v[6]); mnmx4(v[2], v[3], v[4], v[7]); mnmx3(v[3], v[4], v[8]); toVec(gl_FragColor) = v[4]; } #endif
Code: Select all
!!ver 330 !!cvarf glsl_mousex !!cvarf glsl_mousey !!cvarf glsl_velx !!cvarf glsl_vely // author: martins upitis // http://devlog-martinsh.blogspot.it/2011/10/glsl-depth-of-field-with-bokeh-v2.html #ifdef VERTEX_SHADER attribute vec2 v_texcoord; varying vec2 v_edge; void main(void) { gl_Position = ftetransform(); //gl_TexCoord[0] = gl_MultiTexCoord0; v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER varying vec2 v_edge; uniform sampler2D s_t0; uniform float cvar_glsl_mousex;//mouse x position in a cvar!! uniform float cvar_glsl_mousey;//mouse y position in a cvar!! uniform float cvar_glsl_velx;//player velocity x in a cvar!! uniform float cvar_glsl_vely;//player velocity y in a cvar!! uniform sampler2D bgl_RenderedTexture; uniform sampler2D bgl_DepthTexture; uniform float bgl_RenderedTextureWidth; uniform float bgl_RenderedTextureHeight; #define PI 3.14159265 float width = 1920; //texture width float height = 1080; //texture height vec2 texel = vec2(1.0/width,1.0/height); uniform float focalDepth; //focal point. comes from external script, but you may use autofocus option below //------------------------------------------ //user variables int samples = 3; //samples on the first ring int rings = 5; //ring count bool autofocus = false; //use autofocus in shader? float range = 5.0; //focal range float maxblur = cvar_glsl_mousex/30; //clamp value of max blur float threshold = 0.4; //highlight threshold; float gain = 0.0; //highlight gain; float bias = 1; //bokeh edge bias float fringe = 1; //bokeh chromatic aberration/fringing bool noise = true; //use noise instead of pattern for sample dithering float namount = 0.001; //noise amount bool depthblur = true; //blur the depth buffer? float dbsize = 6.0; //depthblursize //------------------------------------------ float bdepth(vec2 coords) //blurring depth { float d = 0.0; float kernel[9]; vec2 offset[9]; vec2 wh = vec2(texel.x, texel.y) * dbsize; offset[0] = vec2(-wh.x,-wh.y); offset[1] = vec2( 0.0, -wh.y); offset[2] = vec2( wh.x -wh.y); offset[3] = vec2( -wh.x, 0.0); offset[4] = vec2( 0.0, 0.0); offset[5] = vec2( wh.x, 0.0); offset[6] = vec2( -wh.x, wh.y); offset[7] = vec2( 0.0, wh.y); offset[8] = vec2( wh.x, wh.y); kernel[0] = 1.0/16.0; kernel[1] = 2.0/16.0; kernel[2] = 1.0/16.0; kernel[3] = 2.0/16.0; kernel[4] = 4.0/16.0; kernel[5] = 2.0/16.0; kernel[6] = 1.0/16.0; kernel[7] = 2.0/16.0; kernel[8] = 1.0/16.0; for( int i = 0; i < 9; i++ ){ float tmp = texture2D(s_t0, coords + offset[i]).r; d += tmp * kernel[i]; } return d; } vec3 color(vec2 coords,float blur) //processing the sample { vec3 col = vec3(0.0); col.r = texture2D(s_t0,coords + vec2(0.0,1.0)*texel*fringe*blur).r; col.g = texture2D(s_t0,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g; col.b = texture2D(s_t0,coords + vec2(0.866,-0.5)*texel*fringe*blur).b; vec3 lumcoeff = vec3(0.299,0.587,0.114); float lum = dot(col.rgb, lumcoeff); float thresh = max((lum-threshold)*gain, 0.0); return col + mix(vec3(0.0),col,thresh*blur); } vec2 rand(in vec2 coord) //generating noise/pattern texture for dithering { float noiseX = ((fract(1.0-coord.s*(width/2.0))*0.25)+(fract(coord.t*(height/2.0))*0.75))*2.0-1.0; float noiseY = ((fract(1.0-coord.s*(width/2.0))*0.75)+(fract(coord.t*(height/2.0))*0.25))*2.0-1.0; if (noise){ noiseX = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233))) * 43758.5453),0.0,1.0)*2.0-1.0; noiseY = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233)*2.0)) * 43758.5453),0.0,1.0)*2.0-1.0; } return vec2(noiseX,noiseY); } void main() { float depth = texture2D(s_t0,v_edge.xy).x; float blur = 0.0; if (depthblur){ depth = bdepth(v_edge.xy); } blur = clamp((abs(depth - focalDepth)/range)*100.0,-maxblur,maxblur); if (autofocus){ float fDepth = texture2D(s_t0,vec2(0.5,0.5)).x; blur = clamp((abs(depth - fDepth)/range)*100.0,-maxblur,maxblur); } vec2 noise = rand(v_edge.xy)*namount*blur; float w = (1.0/width)*blur+noise.x; float h = (1.0/height)*blur+noise.y; vec3 col = texture2D(s_t0, v_edge.xy).rgb; float s = 1.0; int ringsamples; for (int i = 1; i <= rings; i += 1){ ringsamples = i * samples; for (int j = 0 ; j < ringsamples ; j += 1){ float step = PI*2.0 / float(ringsamples); float pw = (cos(float(j)*step)*float(i)); float ph = (sin(float(j)*step)*float(i)); col += color(v_edge.xy + vec2(pw*w,ph*h),blur)*mix(1.0,(float(i))/(float(rings)),bias); s += 1.0*mix(1.0,(float(i))/(float(rings)),bias); } } col /= s; gl_FragColor.rgb = col; gl_FragColor.a = 0; } #endif
- if you want sounds as showed in the video, just download these lame sounds I made just for this project and put them in a sounds subfolder in data folder. Don't worry: released under cc0 public domain license, so no license problem here
- now launch fteqw executable. Open console (shift+ESC key) and you should see "GLSL Showreel initialized" in the top. Type in the console
Close fteqw. Go to the autocreated src folder and rename defs.qc to defs.c. In the src folder add these source files (all released under cc0 public domain license, no problem here)
Code: Select all
pr_dumpplatform -o defs -Ffte -Tcs
progs.srccsqc.cCode: Select all
#pragma PROGS_DAT "../csprogs.dat" #define CSQC #include "defs.c" #include "defscustom.c" #include "fx.c" #include "render.c" #include "csqc.c"
defscustom.cCode: Select all
//GLSL Showreel - created by Antonio "toneddu2000" Latronico and released under CC0 Public Domain license https://creativecommons.org/publicdomain/zero/1.0/ void CSQC_Init(float apilevel, string enginename, float engineversion) { //create sun cvar registercvar("sun_intensity","0.2"); registercvar("sun_height","1000"); //create camera cvar registercvar("camera_speed","0.5"); //create glsl cvars registercvar("glsl_time","0"); registercvar("glsl_mousex","0"); registercvar("glsl_mousey","0"); registercvar("glsl_velx","0"); registercvar("glsl_vely","0"); registercvar("glsl_skysize","0.006"); registercvar("glsl_seasize","0.0006"); registercvar("glsl_seamove","1"); registercvar("glsl_bloomthres","0.45"); registercvar("glsl_bloomintensity","1.2"); //camera camera = spawn(); camera.movetype = MOVETYPE_FLY; setorigin(camera,CAMERA_START_ORIGIN); //glsl init fxName = "ppcolor"; fxTitle = "None"; //fog init localcmd("fog 0.12 0.95 0.95 1.2 0.65 1.5\n"); //ui uiMenu = TRUE; uiMenuQuit = FALSE; uiColorAlpha = 1; uiFlashAlpha = 1; //sounds #ifdef USESOUNDS precache_sound(SOUND_SEA); precache_sound(SOUND_SEAWAVE); precache_sound(SOUND_PORTAL); precache_sound(SOUND_WIND); precache_sound(SOUND_SWITCH); sound(camera,CHAN_AUTO,SOUND_WIND,SOUND_VOL_WIND,0,0,SOUNDFLAG_FORCELOOP); sound(camera,CHAN_WEAPON,SOUND_SEA,SOUND_VOL_SEA,0,0,SOUNDFLAG_FORCELOOP); sound(camera,CHAN_ITEM,SOUND_SEAWAVE,SOUND_VOL_SEAWAVE,0,0,SOUNDFLAG_FORCELOOP); #endif } noref float CSQC_InputEvent(float evtype, float scanx, float chary, float devid) { switch(evtype){ case IE_KEYUP: if (scanx == K_MOUSE1){ fxPostprocessColor = !fxPostprocessColor; if(fxPostprocessColor == TRUE){ uiColorAlpha = 1; } } if (scanx == K_MOUSE2){ fxPostprocessDepth = !fxPostprocessDepth; } if (scanx == K_MWHEELUP){ #ifdef USESOUNDS if(fxPostprocessColor && !uiMenu){ sound(camera,CHAN_VOICE,SOUND_SWITCH,SOUND_VOL_SEA,0); } #endif uiColorAlpha = 0; FX_PlayLoop(); } if (scanx == K_ESCAPE){ uiMenuQuit = FALSE; } //letter N if (scanx == 110){ uiMenu = TRUE; uiMenuQuit = FALSE; } //letter Q if (scanx == 113){ uiMenu = TRUE; uiMenuQuit = TRUE; } //letter Y if (scanx == 121){ if(uiMenuQuit){ localcmd("quit\n"); } } break; } return FALSE; } void CSQC_Input_Frame() { local float spd = cvar("camera_speed"); if(!uiMenu){ makevectors(input_angles); camera.angles = input_angles; camera.velocity = v_forward; camera.velocity *= input_movevalues_x * spd; if(camera.origin_z < CAMERA_LIMIT_GROUND){ camera.origin_z = CAMERA_LIMIT_GROUND+5; } if(camera.origin_z > CAMERA_LIMIT_SKY){ camera.origin_z = CAMERA_LIMIT_SKY-5; } if(vlen(PORTAL1_ORG - camera.origin)<150){ #ifdef USESOUNDS sound(camera,CHAN_VOICE,SOUND_PORTAL,SOUND_VOL_PORTAL,0); #endif uiFlashAlpha = 1; camera.origin = PORTAL2_ORG + [350,0,0]; } if(vlen(PORTAL2_ORG - camera.origin)<150){ #ifdef USESOUNDS sound(camera,CHAN_VOICE,SOUND_PORTAL,SOUND_VOL_PORTAL,0); #endif uiFlashAlpha = 1; camera.origin = PORTAL1_ORG + [-350,0,0]; } } if(cvar("glsl_seamove")==TRUE){ if(camera.velocity_x == 0 && camera.velocity_y == 0 && camera.velocity_z == 0){ camera.origin_z += 0.1 * sin(time * 1); } } } float CSQC_ConsoleCommand(string strMessage) { tokenize(strMessage); switch(argv(0)) { case "togglemenu": uiMenu = !uiMenu; return TRUE; break; } return FALSE; } void CSQC_UpdateView(float vwidth, float vheight, float notmenu) { clearscene(); //fx set vars FX_GlslGetUniformByCvars(); //view properties setviewprop(VF_DRAWWORLD,FALSE); setviewprop(VF_SCREENPSIZE,[vwidth,vheight,0]); setviewprop(VF_SIZE,[vwidth,vheight,0]); setviewprop(VF_ORIGIN, camera.origin); setviewprop(VF_ANGLES, camera.angles); //fx init FX_GlslPostProcessInit(); //add view entities addentities(MASK_ENGINE); //render 3d objects local vector seemov; if(cvar("glsl_seamove") == TRUE){ seemov = [0,0,25*sin(time * 0.9)]; } else{ seemov = [0,0,0]; } Render_Sky(); Render_Sea(); Render_PortalFrame(5,70,100,1,PORTAL1_ORG+[-58.8,0,0]+seemov,"portalframe"); Render_Portal(64,PORTAL1_ORG+seemov,"portal"); Render_PortalFrame(5,70,100,1,PORTAL2_ORG+[-69.1,0,0]+seemov,"portalframe2"); Render_Portal(64,PORTAL2_ORG+seemov,"portal2"); Render_Horizon(); //render scene renderscene(); //fx end FX_GlslPostProcessFlush(); FX_GlslPostProcessStoreToTexture(vwidth,vheight); //ui local string uicolen = "Post process color enabled"; local string uimenutit = "GLSL Showreel - Antonio Latronico"; local string uimenutgl = "ESC key to toggle menu"; local string uimenumouse = "Mouse1 for toggle GLSL color, Mouse2 for toggle GLSL depth"; local string uiquit = "Q key to quit showreel"; local string uiquitmsg = "Do you want to leave showreel?"; local string uiquitconfirm = "Y or N"; local vector uitextcolor = [0.4,0.4,0.4]; local vector uitextsize = [3.5,3.5,0]; local vector uimenutitlesize = [7.5,7.5,0]; local vector uimenutextsize = [5,5,0]; if(uiMenu){ if(!uiMenuQuit){ drawfill([0,0,0],[vwidth,vheight,0],[1,1,1],0.92); drawstring([vwidth-stringwidth(uimenutit,0)*2,40,0],uimenutit,uimenutitlesize,uitextcolor,0.8,0); drawstring([20,70,0],uimenutgl,uimenutextsize,uitextcolor,0.8,0); drawstring([20,100,0],uimenumouse,uimenutextsize,uitextcolor,0.8,0); drawstring([20,130,0],uiquit,uimenutextsize,uitextcolor,0.8,0); } else{ drawfill([0,0,0],[vwidth,vheight,0],[1,1,1],1); drawstring([vwidth-(stringwidth(uiquitmsg,0)*2),70,0],uiquitmsg,uimenutextsize,uitextcolor,0.8,0); drawstring([vwidth/2,95,0],uiquitconfirm,uimenutextsize,uitextcolor,0.8,0); } } else{ if(uiFlashAlpha > 0){ uiFlashAlpha -= frametime * 1; } if(fxPostprocessColor){ if(uiColorAlpha > 0){ uiColorAlpha -= frametime * 1; } drawstring([vwidth/2-stringwidth(uicolen,0)/2,100,0],uicolen,[10,10,0],uitextcolor+[0,0.8,0],uiColorAlpha,0); drawstring([20,20,0], "Glsl used: ",uitextsize,uitextcolor,0.5,0); drawstring([65,20,0], fxTitle,uitextsize,uitextcolor+[0,0,1.5],0.9,0); drawstring([20,35,0], "Scroll mouse wheel up to loop post process effects",uitextsize,uitextcolor,0.5,0); } drawfill([1,1,1],[vwidth,vheight,0],[1,1,1],uiFlashAlpha); } }
fx.cCode: Select all
//GLSL Showreel - created by Antonio "toneddu2000" Latronico and released under CC0 Public Domain license https://creativecommons.org/publicdomain/zero/1.0/ //camera entity camera; vector CAMERA_START_ORIGIN = [-400,0,165]; float CAMERA_LIMIT_GROUND = 55; float CAMERA_LIMIT_SKY = 1200; //fx float fxPostprocessDepth, fxPostprocessColor, fxGlslTimer, fxLoop; string fxName, fxTitle; float FX_TOTAL = 6; //ui float uiMenu,uiMenuQuit,uiColorAlpha,uiFlashAlpha; //portal vector PORTAL1_ORG = [0,0,150]; vector PORTAL2_ORG = [-2000,0,150]; //sounds //#define USESOUNDS #ifdef USESOUNDS string SOUND_SEA = "sounds/water.wav"; string SOUND_SEAWAVE = "sounds/seawave.wav"; string SOUND_PORTAL = "sounds/portal.wav"; string SOUND_WIND = "sounds/wind_loop.wav"; string SOUND_SWITCH = "sounds/switch.wav"; float SOUND_VOL_SEA = 0.5; float SOUND_VOL_SEAWAVE = 0.85; float SOUND_VOL_WIND = 3.5; float SOUND_VOL_PORTAL = 6; #endif
render.cCode: Select all
//GLSL Showreel - created by Antonio "toneddu2000" Latronico and released under CC0 Public Domain license https://creativecommons.org/publicdomain/zero/1.0/ void FX_PlayLoop() { fxLoop++; if(fxLoop > FX_TOTAL){ fxLoop = 0; } //increase here for new effects switch(fxLoop){ case 0: fxName = "ppcolor"; fxTitle = "None"; break; case 1: fxName = "ppbandw"; fxTitle = "Black and white"; break; case 2: fxName = "ppmblur"; fxTitle = "Motion blur"; break; case 3: fxName = "ppchrom"; fxTitle = "Chromatic aberration"; break; case 4: fxName = "ppascii"; fxTitle = "Ascii code"; break; case 5: fxName = "ppbloom"; fxTitle = "Bloom"; break; case 6: fxName = "ppmedian"; fxTitle = "Median point"; break; default: fxName = ""; break; } } void FX_GlslPostProcessVarsInit() { fxPostprocessDepth = TRUE; fxPostprocessColor = TRUE; } void FX_GlslPostProcessInit() { local float sizex = cvar("vid_width"); local float sizey = cvar("vid_height"); local vector r = [sizex,sizey,0]; //rt shaders to compile. Order matters! Latter will be seen! if(fxPostprocessDepth == TRUE){ setproperty(VF_RT_DEPTH, "ppdepth", 4,r); setviewprop(VF_SIZE, r); } if(fxPostprocessColor == TRUE){ setproperty(VF_RT_DESTCOLOUR, fxName, 1, r); setviewprop(VF_SIZE, r); } } void FX_GlslPostProcessFlush() { //flush fx or scene won't be rendered if(fxPostprocessDepth == TRUE){ setproperty(VF_RT_DEPTH, ""); } if(fxPostprocessColor == TRUE){ setproperty(VF_RT_DESTCOLOUR, ""); } } void FX_GlslPostProcessStoreToTexture(float screenwidth,float screenheight) { //store postprocess in shader which has $rt: keyword if(fxPostprocessColor == TRUE){ drawpic([0,0,0],fxName,[screenwidth,screenheight,0],[1,1,1],1); } if(fxPostprocessDepth == TRUE){ drawpic([0,0,0],"ppdepth",[screenwidth,screenheight,0],[1,1,1],1); } } void FX_GlslGetUniformByCvars() { //setting vars to cvars, which have uniform corrispective in glsl shader. //add time fxGlslTimer = time; localcmd(strcat("glsl_time ",ftos(fxGlslTimer),"\n")); //add mouse position (for motion blur stuff) local vector mpos = getmousepos(); localcmd(strcat("glsl_mousex ",ftos(mpos_x),"\n")); localcmd(strcat("glsl_mousey ",ftos(mpos_y),"\n")); //add velocity localcmd(strcat("glsl_velx ",ftos(camera.velocity_x),"\n")); localcmd(strcat("glsl_vely ",ftos(camera.velocity_y),"\n")); }
Code: Select all
//GLSL Showreel - created by Antonio "toneddu2000" Latronico and released under CC0 Public Domain license https://creativecommons.org/publicdomain/zero/1.0/ void Render_Cube(float side,vector org) { local string shd = "cube"; //left_ok R_BeginPolygon(shd); R_PolygonVertex([-side,side,side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([side,side,-side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // top_ok R_PolygonVertex([side,-side,side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,side,side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,-side,side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // back_ok R_PolygonVertex([side,side,-side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([side,-side,side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([side,-side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // right_ok R_PolygonVertex([side,-side,side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([-side,-side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,-side,-side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([side,-side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // bottom_ok R_PolygonVertex([side,side,-side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,-side,-side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,-side,-side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); } void Render_PortalFrame(float sd1,float sd2,float sd3,float size, vector org,string shd) { local float side1 = sd1 * size; local float side2 = sd2 * size; local float side3 = sd3 * size; R_BeginPolygon(shd); R_PolygonVertex([-side1, side2, -side3]+org,[-1, 0, 0],[1,1,1],1); R_PolygonVertex([-side1, -side2, -side3]+org,[-1, 0, 0],[1,1,1],1); R_PolygonVertex([-side1, -side2, side3]+org,[-1, 0, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([-side1, -side2, side3]+org,[-1, 0, 0],[1,1,1],1); R_PolygonVertex([-side1, side2, side3]+org,[-1, 0, 0],[1,1,1],1); R_PolygonVertex([-side1, side2, -side3]+org,[-1, 0, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([-side1, side2, side3]+org,[0, 1, 0],[1,1,1],1); R_PolygonVertex([side1, side2, side3]+org,[0, 1, 0],[1,1,1],1); R_PolygonVertex([side1, side2, -side3]+org,[0, 1, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([side1, side2, -side3]+org,[0, 1, 0],[1,1,1],1); R_PolygonVertex([-side1, side2, -side3]+org,[0, 1, 0],[1,1,1],1); R_PolygonVertex([-side1, side2, side3]+org,[0, 1, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([side1, side2, side3]+org,[1, 0, 0],[1,1,1],1); R_PolygonVertex([side1, -side2, side3]+org,[1, 0, 0],[1,1,1],1); R_PolygonVertex([side1, -side2, -side3]+org,[1, 0, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([side1, -side2, -side3]+org,[1, 0, 0],[1,1,1],1); R_PolygonVertex([side1, side2, -side3]+org,[1, 0, 0],[1,1,1],1); R_PolygonVertex([side1, side2, side3]+org,[1, 0, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([-side1, -side2, -side3]+org,[0, -1, 0],[1,1,1],1); R_PolygonVertex([side1, -side2, -side3]+org,[0, -1, 0],[1,1,1],1); R_PolygonVertex([side1, -side2, side3]+org,[0, -1, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([side1, -side2, side3]+org,[0, -1, 0],[1,1,1],1); R_PolygonVertex([-side1, -side2, side3]+org,[0, -1, 0],[1,1,1],1); R_PolygonVertex([-side1, -side2, -side3]+org,[0, -1, 0],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([-side1, -side2, -side3]+org,[0, 0, -1],[1,1,1],1); R_PolygonVertex([-side1, side2, -side3]+org,[0, 0, -1],[1,1,1],1); R_PolygonVertex([side1, side2, -side3]+org,[0, 0, -1],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([side1, side2, -side3]+org,[0, 0, -1],[1,1,1],1); R_PolygonVertex([side1, -side2, -side3]+org,[0, 0, -1],[1,1,1],1); R_PolygonVertex([-side1, -side2, -side3]+org,[0, 0, -1],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([side1, -side2, side3]+org,[0, 0, 1],[1,1,1],1); R_PolygonVertex([side1, side2, side3]+org,[0, 0, 1],[1,1,1],1); R_PolygonVertex([-side1, side2, side3]+org,[0, 0, 1],[1,1,1],1); R_EndPolygon(); R_PolygonVertex([-side1, side2, side3]+org,[0, 0, 1],[1,1,1],1); R_PolygonVertex([-side1, -side2, side3]+org,[0, 0, 1],[1,1,1],1); R_PolygonVertex([side1, -side2, side3]+org,[0, 0, 1],[1,1,1],1); R_EndPolygon(); } void Render_Portal(float side, vector org,string shd) { local float z = 1.47; R_BeginPolygon(shd); // left(is front) R_PolygonVertex([-side,-side,side*z]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([-side,side,side*z]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,side,-side*z]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,-side,-side*z]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); } void Render_Sky() { local string shd = "sky"; local float side = 1048576*10; local float z = 10000; R_BeginPolygon(shd); R_PolygonVertex([side,-side,z],[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,z],[1,1,0],[1,1,1],1); R_PolygonVertex([-side,side,z],[1,0,0],[1,1,1],1); R_PolygonVertex([-side,-side,z],[0,0,0],[1,1,1],1); R_EndPolygon(); } void Render_Horizon() { local string shd = "horizon"; local float side = 1048576*10; local float z = 10000; local vector org; makevectors(input_angles); org = camera.origin +(v_forward * 10000); // front R_BeginPolygon(shd); R_PolygonVertex([-side,side,side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([side,side,-side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // top R_PolygonVertex([side,-side,side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,side,side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,-side,side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // right R_PolygonVertex([side,side,-side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([side,-side,side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([side,-side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // left R_PolygonVertex([-side,-side,side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([-side,side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,side,-side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,-side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // bottom R_PolygonVertex([side,-side,side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([-side,-side,side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,-side,-side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([side,-side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); // back R_PolygonVertex([side,side,-side]+org,[0,1,0],[1,1,1],1); R_PolygonVertex([side,-side,-side]+org,[1,1,0],[1,1,1],1); R_PolygonVertex([-side,-side,-side]+org,[1,0,0],[1,1,1],1); R_PolygonVertex([-side,side,-side]+org,[0,0,0],[1,1,1],1); R_EndPolygon(); } void Render_Sea() { local string shd = "sea"; local float side = 1048576; local float z = 15; // front R_BeginPolygon(shd); R_PolygonVertex([side,-side,z],[0,1,0],[1,1,1],1); R_PolygonVertex([side,side,z],[1,1,0],[1,1,1],1); R_PolygonVertex([-side,side,z],[1,0,0],[1,1,1],1); R_PolygonVertex([-side,-side,z],[0,0,0],[1,1,1],1); R_EndPolygon(); }
- now create in data folder a default.cfg file and edit like this:
Code: Select all
//make sure csqc runs without a server set pr_csqc_formenus 1 //resolution vid_fullscreen_standalone 1 vid_width 1920 vid_height 1080 //input bind a +moveleft bind d +moveright bind w +forward bind s +back //graphics vid_multisample 4 r_fxaa 8 fov 120
- Ok it's time to compile. SOUNDS WARNING: if you want lame sounds enabled, just go to defscustom.c and uncomment #define USESOUNDS, remember to download my sounds file
Open fteqw executable, open console and typeIf you copy everything correctly (and I didn't miss anything ), engine should print somthing likeCode: Select all
compile
Now close fteqw and reopen it. It *should* be exactly like the one in the video!Code: Select all
Compile finished. It took blablabla seconds. 0 Warnings. Done.
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
How GLSL files work:
For those who never heard of, GLSL stands for OpenGL shading Language and it's a C-syntax-like shader file that permits "to draw something on screen": that could be an entire 3d scene (take a look at some beautiful works at shadertoy), a 2d scene, a post-processing 2d effect or even a "living texture" put on top of a 3d mesh.
GLSL file is divided in two parts, vertex shader and fragment shader. Vertex shader manages vertex positions in space and time, fragment position is about pixels colors, alpha in space and time. In fragment you can also retrieve textures and edit them
There are many file types in GLSL: vec2,vec3,vec4,int,float, and other I didn't even tried (like matricies) but for now let's concentrate on these types.
A vec2 is like an array of 2 elements and it's declared like this vec2 foo = vec2(15.0,12.1); and its values can be retrieved singularly like this foo.x = 15.0 foo.y = 12.1 vec2 is usually used for 2d coords (that's why I used .x and .y but I could use .r and .g or .s and .t without any problem)
a vec3 is like vec2 but with 3 elements, it's often used for rgb colors. vec3 foo = vec3(1.0,0.1,0.1); -> foo.r = 1.0,and so on
a vec4 is like vec3 plus a 4th element that's usually used for opacity, so vec4 foo = vec4(1,0,0.0,0.0,0.5) it's an half transparent red
Variables qualifiers are explained a lot well here, so why bother re-explaining them again? In FTE, qualifiers are used like this:
- uniform is used by some actor that needs to talk to GLSL. An example: using cvars to control GLSL in CSQC. Using uniform it's the only way (at least that I know) to export from FTE csqc a var and import it in GSLS shader. A typical example is time. You set a cvar, apply time value to that cvar through localcmd, declare it in GLSL header and then use it (it will be explained in detail later)
- varying is used to share a var between vertex and fragment parts. An example is v_edge var (I used always this var name as Spike did in his GLSL files), which stores uv coordinates in vertex shader as long as it can be used in fragment shader (imagine to make a texture scroll in fragment shader: v_edge.x * time, for example)
- regular var types without qualifiers can be used as global scope (for global scope I mean through all the entire vertex shader and through all the entire fragment shader) and local scope
Inside vertex main block I usually just write
Inside fragment main block you have to write at least a GL_FragColor() func to draw anything. For example: GL_FragColor(1.0,0.0,0.0,1.0); it will draw a red solid color
To pass a CSQC var to GLSL file (game time for example), do like this.
- create a cvar (for example name it glsl_time)in your CSQC_Init via registercvar or put it in your default.cfg file (both methods are OK).
- declare it on top of GLSL file, just after version number (REMEMBER: version number MUST be first line in GLSL file or it will throw an error!)
Code: Select all
!!cvarf glsl_time
- Create an uniform float in fragment block that comprehends cvar name + "cvar_" prefix
Code: Select all
uniform float cvar_glsl_time;
- use it in your fragment block
Code: Select all
void main(void) { float time = cvar_glsl_time; v_edge.x = time * 0.1;//scroll texture horizontally }
- In vertex block add a vec2 v_edge that stores UV texture coordinates and a system attribute vec2 v_texcoord (do NOT change its name!) that reads engine 3d model uv's
Then in main block make sure uv tex coords are applied to the "shared" v_edge vec2. Don't ask me about gl_Position, because I don't know how engine handles it. Ask Spike instead
Code: Select all
attribute vec2 v_texcoord; varying vec2 v_edge;
Code: Select all
void main(void) { gl_Position = ftetransform(); v_edge = v_texcoord.xy; }
- In GLSL fragment block define a sampler2D (which is a bidimensional texture in GLSL) and, of course another "copy" of v_edge as vertex copy of uv's
In fragment main block
Code: Select all
varying vec2 v_edge; uniform sampler2D s_t0;
Code: Select all
void main(void) { vec4 img = texture2D( s_t0, v_edge); GL_FragColor = img; }
- In shader file you have to put a texture definition that links to s_t0 glsl texture. For example:
Code: Select all
exampleshader { program ton_myglslfile { diffusemap textures/example_diff.tga } }
- If you want more than one textures(diffuse, specular, normal, etc.) and you want to manage them in GLSL, you have to make sure that order of textures in shader file must be the order of sampler2D in glsl file. For example:
shader fileglsl file - fragment blockCode: Select all
exampleshader { program ton_myglslfile { diffusemap textures/example_diff.tga specularmap textures/example_spec.tga normalmap textures/example_normal.tga } }
Then, in fragment main blockCode: Select all
varying vec2 v_edge; uniform sampler2D s_t0;//diffuse uniform sampler2D s_t1;//specular uniform sampler2D s_t2;//normal
Code: Select all
void main(void) { vec4 dif = texture2D( s_t0, v_edge); vec4 spec = texture2D( s_t1, v_edge); vec4 nor = texture2D( s_t2, v_edge); //now let's do all the complex code to manage them.. }
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
Did you try something like sung light beams!! ??
Fte is so powerful, this helps a lot to all who want to get into this engine (I include myself)
I think I'm going to add some shader of these and test them with FREE-CS !!
I would really like to see some of those powerful shaders acting on counter strike 1.5 !!
I wonder what limitations there are in FTE for glsl !!! And if there is a distant possibility of doing something similar in DP (you know, csqc interacting with shaders) I still hope
Incredible, thank you very much.
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
Like god rays? No, I didn't try and, honestly, I dunno know where to start. The problem is that you should be able to create some sort of bloom only when glsl intercepts a "sun entity"(bloom effect in glsl showreel could do the job), but I don't know how to isolate only a specific region of pixels (maybe by color?) and then apply the effectNahuel wrote:Did you try something like sung light beams!! ??
Yeah, fte is awesome, it has an endless list of builtin functions to make practically every kind of game (well, car physics game excluded, maybe)Nahuel wrote:Fte is so powerful, this helps a lot to all who want to get into this engine (I include myself)
Cool! Post your works on insideqc so we'll see themNahuel wrote:I think I'm going to add some shader of these and test them with FREE-CS !!
Regarding dp no idea, but about limitations, don't know if there are any, only thing I know is that creating post-processing effect that envolve depth buffer use (ambient occlusion, depth of field, etc.) are extremely difficult to achieve. Just to make an example: in GLSL Showreel if you press right mouse click you see depth buffer, but, as many techniques I tried, I NEVER accomplished to store it to re-use in the shader.Nahuel wrote:I wonder what limitations there are in FTE for glsl !!! And if there is a distant possibility of doing something similar in DP (you know, csqc interacting with shaders) I still hope
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
Maybe we should start a wiki on github or so where we can put all the nice documentation in one place? I wish Spike would finally use it or gitlab for the code and bugtracker as well... the current svn sourceforge repository is atrocious (not even talking about the outdated website ).
By the way, do GLSL shaders work seamlessly with the Vulkan renderer as well?
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
Probably a wiki would be great, but don't count on Spike: he HATES writing documentation, he prefers help devs on this forum so it's up to us to collect his answers and assemble them in a formal document. That's also why I created GLSL showreel. My intent is, everytime I learn something about the use of GLSL (in general and/or related to FTE), to update this topic as it can be shared with other users.Julius wrote:Maybe we should start a wiki on github or so where we can put all the nice documentation in one place? I wish Spike would finally use it or gitlab for the code and bugtracker as well... the current svn sourceforge repository is atrocious (not even talking about the outdated website ).
As far as I understood (but not count on my words as I'm not an expert) you'll need a GLSL to SPIR-V compiler which compiles GLSL files in SPIR-V shaders, which are way more low-level than GLSL shaders, making things easier for driver manufacturersJulius wrote:By the way, do GLSL shaders work seamlessly with the Vulkan renderer as well?
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
regarding vulkan, the renderer I wrote does not contain its own glsl compiler thus it currently requires precompiled glsl, which means that all the ifdef stuff cannot work the same as with the gl renderer. instead it depends upon vulkan's specialisation constants for permutations and parms.
this sucks, of course so I really ougt to try and figure out some better solution some time.
nvidia drivers embed a glsl compiler but have no reflection stuff, iirc my implementation of it is also limited and can't handle permutations, and of course vendor specific so whatever.
but yeah, (optimised) spirv not having any reflection info means that fte depends upon metadata which requires specialised tools... specifically the 'makevulkanblob.c' program on fte's svn. it depends upon glslang's spirv compiler (which has various bugs with specialisation constants so I had to keep it using some old version of the vulkan sdk to avoid the worst of it). really the whole thing sucks.
so yeah, I don't really expect anyone to try writing any glsl/spir-v for fte's vulkan renderer.
toneddu2000, you might want to use s_diffuse/s_specular etc in your glsl instead of assuming that s_t0, s_t1 etc match them. doing so means that you can skip the extra {map foo} blocks in your .shader (although annoyingly you normally still need one, in order to specify the blend mode properly).
god rays: http://triptohell.info/moodles/junk/fte00016.jpg - just set r_sun_colour (and don't use a skybox)
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
Wow,didn't know that. Is this the function?Spike wrote: depth: be aware that depth buffers are non-linear. the lpp_light.glsl fragment shader has some function to convert a depth value and texture coord back into a 3d worldspace coord. if you just try drawing the depth buffer as-is then yeah, you'll probably just get something really close to black.
Code: Select all
vec3 calcLightWorldPos(vec2 screenPos, float depth)
{
vec4 pos = m_invviewprojection * vec4(screenPos.xy, (depth*2.0)-1.0, 1.0);
return pos.xyz / pos.w;
}
This is the depth GLSL file. Very very basic
Code: Select all
!!ver 330
// author: Antonio "toneddu2000" Latronico
// placed under cc0 public domain license
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
varying vec2 v_edge;
void main(void)
{
gl_Position = ftetransform();
v_edge = v_texcoord.xy;
}
#endif
#ifdef FRAGMENT_SHADER
varying vec2 v_edge;
uniform sampler2D s_t0;
void main(void)
{
vec3 img;
img = vec3(texture2D(s_t0,v_edge.xy));
gl_FragColor = vec4(img,1);
}
#endif
That's..awesome! Thanks a lot Spike! That helps a lot!Spike wrote: toneddu2000, you might want to use s_diffuse/s_specular etc in your glsl instead of assuming that s_t0, s_t1 etc match them. doing so means that you can skip the extra {map foo} blocks in your .shader (although annoyingly you normally still need one, in order to specify the blend mode properly).
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
This is what you told me about light prepass in fte
- add to wall this shader
Code: Select all
somewallshader { fte_program lpp_wall { map $sourcecolour } //this is drawn during the gbuffer pass to prepare it fte_bemode gbuffer { fte_program lpp_depthnorm { map $normalmap } } }
- particle script with embedded GLSL
Code: Select all
r_lightprepass 2 r_part tr_rocket { shader "particles/myprelight" { glslprogram { varying vec4 tf; varying vec3 lpos; varying vec4 lightColour; #define lightradius (300.0)// * 0.25) #ifdef VERTEX_SHADER attribute vec2 v_texcoord; attribute vec4 v_colour; uniform mat4 m_view; void main(void) { vec3 fwd, right, up; right.x = m_view[0].x; right.y = m_view[1].x; right.z = m_view[2].x; up.x = m_view[0].y; up.y = m_view[1].y; up.z = m_view[2].y; fwd.x = m_view[0].z; fwd.y = m_view[1].z; fwd.z = m_view[2].z; lpos = v_position; lpos += 1.5*(v_texcoord.x-0.5) * right * lightradius; lpos += 1.5*(v_texcoord.y-0.5) * up * lightradius; lpos.z += 2.0; lightColour = v_colour; gl_Position = tf = m_modelviewprojection * vec4(v_position.xyz, 1.0); } #endif #ifdef FRAGMENT_SHADER uniform sampler2D s_t0; uniform mat4 m_invviewprojection; vec3 calcLightWorldPos(vec2 screenPos, float depth) { vec4 pos = m_invviewprojection * vec4(screenPos.xy, (depth*2.0)-1.0, 1.0); return pos.xyz / pos.w; } void main (void) { float lightAttenuation = lightradius*0.5; float radiusFar = lightradius*0.5; float radiusNear = lightradius*0.25; vec2 fc; fc = tf.xy / tf.w; vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0); float depth = data.a; vec3 norm = data.xyz; vec3 worldPos = calcLightWorldPos(fc, depth); vec3 lightDir = lpos - worldPos; float zdiff = 1.0 - clamp(length(lightDir) / lightAttenuation, 0.0, 1.0); float atten = (radiusFar * zdiff) / (radiusFar - radiusNear); atten = pow(atten, 2.0); lightDir = normalize(lightDir); float nDotL = dot(norm, lightDir) * atten; float lightDiffuse = max(0.0, nDotL); gl_FragColor = vec4(lightDiffuse * (lightColour.rgb), lightColour.a); //gl_FragColor = vec4(lightColour); //gl_FragColor = vec4(lightDir, 1.0); } #endif } { map $sourcecolour blend gl_src_alpha gl_one nodepthtest } surfaceparm nodlight lpp_light } step 8 scale 300 alpha 10 die 5 rgbrand 255 255 255 scalefactor 1 gravity 200 spawnmode box 500 100 spawnvel 200 friction 2 // clipbounce 0 // cliptype tr_rocket rotationstart 225 } r_part +tr_rocket { texture "ball" step 8 scale 4 alpha 10 die 5 rgbrand 255 255 255 scalefactor 1 gravity 200 spawnmode box 500 100 spawnvel 200 friction 2 rotationstart 225 } r_part te_explosion { shader "particles/myprelight" scale 300 die 4 rgb 128 255 128 scalefactor 1 rotationstart 225 spawnvel 64 gravity 200 count 40[*][*] } r_part +te_explosion { texture "ball" scale 4 die 4 rgb 255 128 255 scalefactor 1 rotationstart 225 spawnvel 64 gravity 200 count 40 }
- and then
Code: Select all
r_lightprepass 1
Code: Select all
vid_reload
Adding ssao + deferred light would boost fte's renderer quality at its best!
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
deferred lights are basically just a sprite that covers the parts of the screen that the light should affect. These 'sprites' can either be provided via the engine from the .rtlights file/adddynamiclight builtin, or you can provide them as actual sprites yourself.
If your shader has the lpp_light directive inside it, then it will be 'drawn' after the regular gbuffer pass and before the lpp_wall stuff. its input texture will be the normalmap and depth values from the lpp_depthnorm shaders over the underlaying geometry, and its output is the raw lighting values. the lpp_wall shader is then given the output of those lighting 'sprites', and combines the lighting values with the diffuse textures.
its all single outputs right now, which means specular with deferred shading cannot really work right now. I'd like to come up with some nice configurable way to make the gbuffers extensible to allow for other effects, but I've not really gotten around to finalising anything in that regard (especially as I'd want it to apply to the vk+d3d11 renderers eventually too).
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
This is what I did, I premise that in Glsl Showreel I'm usingSpike wrote:regarding depth, remember to divide any projected texture coords by w before passing them to that function. read up on homogeneous coords some time for why this is needed.
Code: Select all
setviewprop(VF_DRAWWORLD,FALSE);
so probably it's not the best scenario to test depth
in csqc, in CSQC_UpdateView() I call
Code: Select all
if(fxPostprocessDepth == TRUE){
setproperty(VF_RT_DEPTH, "ppdepth", 4,r);
setviewprop(VF_SIZE, r);
}
if(fxPostprocessColor == TRUE){
setproperty(VF_RT_DESTCOLOUR, fxName, 1, r);
setviewprop(VF_SIZE, r);
}
This is what I tried for depth glsl file
Code: Select all
!!ver 130
!!cvarf glsl_depth
varying vec4 tf;
varying vec2 uvcoords;
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
void main ()
{
tf = ftetransform();
gl_Position = tf;
uvcoords = v_texcoord.xy;
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
uniform mat4 m_invviewprojection;
uniform float cvar_glsl_depth;
vec3 calcLightWorldPos(vec2 screenPos, float depth)
{
vec4 pos = m_invviewprojection * vec4(screenPos.xy, (depth*2.0)-1.0, 1.0);
return pos.xyz / pos.w;
}
void main ()
{
vec2 fc;
fc = tf.xy / tf.w;
//invert y axis otherwise img will be upside-down
fc.y = -fc.y;
vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0);
float depth = data.a;
vec3 norm = data.xyz;
vec3 worldPos = calcLightWorldPos((1.0 + fc) / 2.0, depth);
//normal img
vec4 img = texture2D(s_t0,uvcoords);
//test depth
if(cvar_glsl_depth == 1){
gl_FragColor = data;
}
else if(cvar_glsl_depth == 2){
gl_FragColor = vec4(worldPos,depth);
}
else{
gl_FragColor = img*depth;
}
}
#endif
If I switch to 2, screen becomes yellow (obviously) and a red and blue line appear above and left. I guess calcLightWorldPos() returns some sort of coordinates (so, of course, it's not usable with gl_FragColor directly) but I guess it won't help me for test I'm trying to accomplish, also because I think it's related somehow to light position and, in my scene, there are no lights.
I'd just like to understand if depth var is storing some information. So I tried to combine with .rgb in gl_FragColor but is always white, even when I go close to objects, but depth post process shows different shades of gray when I'm standing near to portals, so, obviously, it's doing stuff..
Tried same code even in post-process color and no changes at all. So, my question is: is depth buffer visible (retrievable, computable, choose the term you prefer) in depth post processing pass, color post-processing pass or both? Because, right now depth post processing pass it's useful to me just to say that I implemented it, but, apart from that, I cannot understand how to use it.
Another thing I fixed. Myself said today:
Well, I was making a mistake. Toggling on post-process color makes the post-process depth pass (when enabled) to be aligned with color pass. Probably non-post-processed pass and post-processed pass use different system of coordinates or.. i dunnotoneddu2000 wrote:Regarding depth..if you compile GLSL showreel and toggle depth on/off with right mouse click, you'll notice that depth image coords is not "aligned". For example, if you stare at the portal box, and switch depth on, you'll see that box is stretched and stands more on the right respect color pass, like if the image was zoomed...Do I miss something?
Wow...it will take a week to make a test like this and be sure to try all the possibilities. Thanks Spike, I'll post all the tests hereSpike wrote:deferred lights are basically just a sprite that covers the parts of the screen that the light should affect. These 'sprites' can either be provided via the engine from the .rtlights file/adddynamiclight builtin, or you can provide them as actual sprites yourself.
If your shader has the lpp_light directive inside it, then it will be 'drawn' after the regular gbuffer pass and before the lpp_wall stuff. its input texture will be the normalmap and depth values from the lpp_depthnorm shaders over the underlaying geometry, and its output is the raw lighting values. the lpp_wall shader is then given the output of those lighting 'sprites', and combines the lighting values with the diffuse textures.
its all single outputs right now, which means specular with deferred shading cannot really work right now. I'd like to come up with some nice configurable way to make the gbuffers extensible to allow for other effects, but I've not really gotten around to finalising anything in that regard (especially as I'd want it to apply to the vk+d3d11 renderers eventually too).
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: [FTEQW][REL]GLSL showreel - also mini tutorial
If you try GLSL showreel with FTE version superior to v5343, you'll see a checker texture that it's displayed instead of 3d scene, when postrprocessing is enabled. That's because Spike added "Lazy glsl loading" in v5344, which essentually avoid to use custom glsl stuff by forcing to use fteisms like !!samps for better loading performances. Let's take a look at how it works. Let's create a simple GLSL post processing
CSQC_UpdateView
Code: Select all
void CSQC_UpdateView(float vwidth, float vheight, float notmenu)
{
local vector vsize = [vwidth,vheight,0];
clearscene();
setviewprop(VF_PERSPECTIVE,TRUE);
setviewprop(VF_DRAWCROSSHAIR,TRUE);
Glsl_Update();
renderscene();
Glsl_PostUpdate(vwidth,vheight);
}
Remeber to add setproperty(VF_RT_DESTCOLOUR, ""); after renderscene and before the 2 setptoperty calls, otherwise screen will keep flickering and no image will be rendered.
Code: Select all
void Glsl_Update()
{
local vector psize = (vector)getproperty(VF_SCREENPSIZE); //get the actual size in pixels, so we don't end up with any scaling
local vector vsize = (vector)getproperty(VF_SCREENVSIZE);
setproperty(VF_RT_DESTCOLOUR, "mycolorbuffer", 1, vsize); //rgba8
setproperty(VF_RT_DEPTH, "mydepthbuffer", 6, vsize); //depth32, for lots of precision (3d writes to it, 2d reads from it)
}
void Glsl_PostUpdate(float w,float h)
{
local vector psize = (vector)getproperty(VF_SCREENPSIZE);
local vector vsize = (vector)getproperty(VF_SCREENVSIZE);
//mycolorbuffer and mydepthbuffer now contain the scene colour+depth.
setproperty(VF_RT_DESTCOLOUR, ""); //2d is now drawing to the screen again.
setproperty(VF_RT_SOURCECOLOUR, "mycolorbuffer"); //$sourcecolour now refers to 'mycolorbuffer'
drawpic([0,0], "mypostprocshader", vsize, '1 1 1', 1, 0); //do post processing
setproperty(VF_RT_DEPTH, "mydepthbuffer", 6, vsize); //done reading from that now.
}
shader file in scripts folder. Very simple, first map call is for color buffer, second one is for depth buffer.
Code: Select all
mypostprocshader
{
program simple_postprocess
{
map $sourcecolour
}
{
map $sourcedepth
}
}
Very simple, but take a look at the differences with the past: now, there's no s_t0, s_t1, etc. sampler2D, there are only !!samps call in header that define the samplers. After the sampler name, there's the slot number, in this case 0 is for color (first call) and 1 is for depth (second call), you can use the name you want. For example you can create a !!samps foo:sampler2D=0 and then have access to it using s_foo in glsl. Don't forget the "s_" prefix, though!
Code: Select all
!!ver 330
!!samps dif:sampler2D=0
!!samps dept:sampler2D=1
#include "sys/defs.h"
varying vec2 v_edge;
#ifdef VERTEX_SHADER
void main(void)
{
gl_Position = ftetransform();
v_edge = v_texcoord.xy;
}
#endif
#ifdef FRAGMENT_SHADER
void main(void)
{
vec4 color = texture2D(s_dif,v_edge);
vec4 depth = texture2D(s_dept,v_edge);
float depthval = depth.x*10.0;
gl_FragColor = vec4(color);
}
#endif
Enjoy! And thanks to Spike for his great help!