[FTEQW][REL]GLSL showreel - also mini tutorial

The home for dedicated threads to specific projects, be they mods, tools, or independent games.
Post Reply
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

[FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

Hello guys! It was quite a lot that I had the idea to create some code that showed the muscles underneath GLSL's post processing and shader support in FTE, so.. here it is!
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
Last edited by toneddu2000 on Fri Mar 31, 2017 11:12 am, edited 2 times in total.
Meadow Fun!! - my first commercial game, made with FTEQW game engine
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

Glsl Showreel code
Step-by-step reel creation:
  1. 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)
  2. 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
    
  3. Create a data folder, inside create 2 subfolders: glsl and scripts
  4. 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
    }
    
  5. 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
    	}
    }
    
  6. 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.glsl

    Code: 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_flatcolor.glsl

    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
    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_portal.glsl

    Code: 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_portal2.glsl

    Code: 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_portalframe.glsl

    Code: 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_portalframe2.glsl

    Code: 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
    
    ton_sea.glsl

    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
    
  7. Now let's create, in the same glsl folder, all the glsl files for post processing effects

    ton_pp_ascii.glsl

    Code: 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_bandw.glsl

    Code: 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_basic.glsl

    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(vec3(img.r,img.g,img.b),1);
    }
    #endif
    
    ton_pp_bloom.glsl

    Code: 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_chromaticaberration.glsl

    Code: 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_depth.glsl

    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
    
    ton_pp_median.glsl

    Code: 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
    
    ton_pp_motionblur.glsl

    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
    
  8. 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
  9. now launch fteqw executable. Open console (shift+ESC key) and you should see "GLSL Showreel initialized" in the top. Type in the console

    Code: Select all

    pr_dumpplatform -o defs -Ffte -Tcs
    
    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)

    progs.src

    Code: Select all

    #pragma 	PROGS_DAT "../csprogs.dat"
    #define 	CSQC
    #include	"defs.c"
    #include	"defscustom.c"
    #include	"fx.c"
    #include	"render.c"
    #include	"csqc.c"
    
    csqc.c

    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 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);
    	}
    }
    
    defscustom.c

    Code: 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
    
    fx.c

    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 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"));
    }
    
    render.c

    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();
    }
    
  10. 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
    
  11. 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 type

    Code: Select all

    compile
    
    If you copy everything correctly (and I didn't miss anything :confused: ), engine should print somthing like

    Code: Select all

    Compile finished. It took blablabla seconds.
    0 Warnings. Done.
    
    Now close fteqw and reopen it. It *should* be exactly like the one in the video! :biggrin:
Last edited by toneddu2000 on Sun Apr 02, 2017 10:13 am, edited 2 times in total.
Meadow Fun!! - my first commercial game, made with FTEQW game engine
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

GLSL 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:
  1. 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)
  2. 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)
  3. 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
Main function (for both vertex and fragment shaders) is void main(void){} and their are COMPLETELY separated from each other. If you want that a var is shared by two blocks, you have to declare it in both vertex and fragment block. Textures example below will show you how
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.
  1. 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).
  2. 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
    
  3. Create an uniform float in fragment block that comprehends cvar name + "cvar_" prefix

    Code: Select all

    uniform float cvar_glsl_time;
    
  4. 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 FTEQW textures are used by GLSL in this way
  1. 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

    Code: Select all

    attribute vec2 v_texcoord;
    varying vec2 v_edge;
    
    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

    void main(void)
    {
    	gl_Position = ftetransform();
    	v_edge = v_texcoord.xy;
    }
    
  2. 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

    Code: Select all

    varying vec2 v_edge;
    uniform sampler2D s_t0;
    
    In fragment main block

    Code: Select all

    void main(void)
    {
    	vec4 img = texture2D( s_t0, v_edge);
    	GL_FragColor = img;
    }
    
  3. 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
    	}
    }
    
  4. 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 file

    Code: Select all

    exampleshader
    {
    	program ton_myglslfile
    	{
    		diffusemap	textures/example_diff.tga
    		specularmap	textures/example_spec.tga
    		normalmap	textures/example_normal.tga
    	}
    }
    
    glsl file - fragment block

    Code: Select all

    varying vec2 v_edge;
    uniform sampler2D s_t0;//diffuse
    uniform sampler2D s_t1;//specular
    uniform sampler2D s_t2;//normal
    
    Then, in fragment main block

    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..
    }
    
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Nahuel
Posts: 495
Joined: Wed Jan 12, 2011 8:42 pm
Location: mar del plata

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by Nahuel »

thats GREAT documentation about GLSL and FTE :surprised:

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 :razz:

Incredible, thank you very much.
hi, I am nahuel, I love quake and qc.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

Glad you found it interesting, Nahuel! There are plenty of things to say about GLSL. I'll try to add more stuff
Nahuel wrote:Did you try something like sung light beams!! ??
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 effect
Nahuel wrote:Fte is so powerful, this helps a lot to all who want to get into this engine (I include myself)
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:I think I'm going to add some shader of these and test them with FREE-CS !!
Cool! Post your works on insideqc so we'll see them
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 :razz:
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.
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Julius
Posts: 98
Joined: Sun Aug 29, 2010 4:32 pm
Contact:

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by Julius »

Really helpfull, thanks!

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?
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

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 ;) ).
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:By the way, do GLSL shaders work seamlessly with the Vulkan renderer as well?
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 manufacturers
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by Spike »

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.

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)
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

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.
Wow,didn't know that. Is this the function?

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;
}
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?
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
Could you consider creating a ssao GLSL post-processing file? That would help a lot final rendered image!
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).
That's..awesome! Thanks a lot Spike! That helps a lot!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

Another thing that probably I already asked you and it's a bit off-topic (but not too much) regarding GLSL: at what entity should I apply GLSL lpp_light?
This is what you told me about light prepass in fte
  1. 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
          }
       }
    }
    
  2. 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
    }
    
  3. Code: Select all

    r_lightprepass 1
    and then

    Code: Select all

    vid_reload
    
But, in case I don't want lpp_* particle but a lpp_ light. At what entity I apply lpp_light shader? I cannot apply a shader to a light entity: there's no light entity in csqc as far as I know: I use dynamiclight_add() to draw dynamic lights in CSQC, I never created a light entity that has its own properties. Or should I use .rtlights file to create lights? But, even if I create lights in this way, how can I apply GLSL files to them?

Adding ssao + deferred light would boost fte's renderer quality at its best! :biggrin:
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by Spike »

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.

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).
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

Spike 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.
This is what I did, I premise that in Glsl Showreel I'm using

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);
	}
then I switch on/off postprocess depth with right mouse click and on/off postprocess color with left mouse click, so I can see in realtime where I fail

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 depth mode and change cvar glsl_depth to 0(which was old technique) or 1, no changes at all
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:
toneddu2000 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?
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 dunno
Spike 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).
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 here
Meadow Fun!! - my first commercial game, made with FTEQW game engine
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: [FTEQW][REL]GLSL showreel - also mini tutorial

Post by toneddu2000 »

Important note 31/03/2019 - GLSL post processing in FTE v5344+

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);
}
GLSL render functions. Note that "mycolorbuffer" and "mydepthbuffer" are made-up names, you can chose whatever name for each, as long as it's the same while writing it AND reading it.
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
	}
}
simple_postprocess.glsl file.
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
As you probably noted, depth buffer is read on the .x values, then you have to do some math to use it. I've never been able to use it, but, if you can, for example, add Screen Space Ambient Occlusion, please post your code here!
Enjoy! And thanks to Spike for his great help!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Post Reply