[require] GLSL >= 1.10 [vertex shader] #version 120 #extension GL_ARB_texture_rectangle : enable #define flat #define texture2DRectOffset(sampler, coords, offset) texture2DRect(sampler, coords + vec2(offset)) #define shadow2DRectOffset(sampler, coords, offset) shadow2DRect(sampler, coords + vec2(offset)) attribute vec4 vvertex; uniform mat4 lightmatrix; void main(void) { gl_Position = lightmatrix * vvertex; } [fragment shader] #version 120 #extension GL_ARB_texture_rectangle : enable #define flat #define texture2DRectOffset(sampler, coords, offset) texture2DRect(sampler, coords + vec2(offset)) #define shadow2DRectOffset(sampler, coords, offset) shadow2DRect(sampler, coords + vec2(offset)) #define fragdata(loc, name, type) #define fragcolor gl_FragData[0] uniform sampler2DRect tex0, tex1, tex3 , tex2; uniform sampler2DRectShadow tex4; uniform vec4 lightpos[5]; uniform vec3 lightcolor[5]; uniform vec4 shadowparams[5]; uniform vec2 shadowoffset[5]; uniform vec3 splitcenter[3]; uniform vec3 splitbounds[3]; uniform vec3 splitscale[3]; uniform vec3 splitoffset[3]; uniform vec3 camera; uniform mat4 worldmatrix; uniform vec4 fogdir; uniform vec3 fogcolor; uniform vec2 fogdensity; uniform vec4 radialfogscale; uniform vec2 shadowatlasscale; uniform vec4 lightscale; uniform vec3 gdepthscale; uniform vec3 gdepthunpackparams; fragdata(0, fragcolor, vec4) vec3 getshadowtc(vec3 dir, vec4 shadowparams, vec2 shadowoffset, float distbias) { vec3 adir = abs(dir); float m = max(adir.x, adir.y), mz = max(adir.z, m); vec2 mparams = shadowparams.xy / max(mz + distbias, 1e-5); vec4 proj; if(adir.x > adir.y) proj = vec4(dir.zyx, 0.0); else proj = vec4(dir.xzy, 1.0); if(adir.z > m) proj = vec4(dir, 2.0); return vec3(proj.xy * mparams.x + vec2(proj.w, step(proj.z, 0.0)) * shadowparams.z + shadowoffset, mparams.y + shadowparams.w); } #define shadowval(center, xoff, yoff) float(shadow2DRect(tex4, center + vec3(xoff, yoff, 0.0))) float filtershadow(vec3 shadowtc) { vec2 offset = fract(shadowtc.xy - 0.5); vec3 center = shadowtc; center.xy -= offset*0.5; vec4 size = vec4(offset + 1.0, 2.0 - offset); return (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(shadowval(center, -0.5, -0.5), shadowval(center, 1.0, -0.5), shadowval(center, -0.5, 1.0), shadowval(center, 1.0, 1.0))); } void main(void) { #define gfetch(sampler, coords) texture2DRect(sampler, coords) #define accumlight(light) fragcolor.rgb = light #define accumalpha(alpha) fragcolor.a = alpha vec4 normal = gfetch(tex1, gl_FragCoord.xy); normal.xyz = normal.xyz*2.0 - 1.0; #define alpha normal.a vec4 diffuse = gfetch(tex0, gl_FragCoord.xy); #define depthvals gfetch(tex3, gl_FragCoord.xy) float depth = depthvals.r; vec4 pos = worldmatrix * vec4(gl_FragCoord.xy, depth, 1.0); pos.xyz /= pos.w; float fogcoord = length(camera - pos.xyz); #define distbias 0.0 vec3 camdir = normalize(camera - pos.xyz); float facing = 2.0*dot(normal.xyz, camdir); vec3 light = vec3(0.0); vec3 light0dir = pos.xyz * lightpos[0].w - lightpos[0].xyz; float light0dist2 = dot(light0dir, light0dir); if(light0dist2 < 1.0) { float light0facing = dot(light0dir, normal.xyz); if(light0facing < 0.0) { float light0invdist = inversesqrt(light0dist2); float light0atten = light0facing * (1.0 - light0invdist); vec3 shadow0tc = getshadowtc(light0dir, shadowparams[0], shadowoffset[0], distbias * lightpos[0].w); light0atten *= filtershadow(shadow0tc); float light0spec = pow(clamp(light0invdist*(dot(camdir, light0dir) - light0facing*facing), 0.0, 1.0), 16.0) * diffuse.a; light += (diffuse.rgb + light0spec) * lightcolor[0] * light0atten; } } vec3 light1dir = pos.xyz * lightpos[1].w - lightpos[1].xyz; float light1dist2 = dot(light1dir, light1dir); if(light1dist2 < 1.0) { float light1facing = dot(light1dir, normal.xyz); if(light1facing < 0.0) { float light1invdist = inversesqrt(light1dist2); float light1atten = light1facing * (1.0 - light1invdist); vec3 shadow1tc = getshadowtc(light1dir, shadowparams[1], shadowoffset[1], distbias * lightpos[1].w); light1atten *= filtershadow(shadow1tc); float light1spec = pow(clamp(light1invdist*(dot(camdir, light1dir) - light1facing*facing), 0.0, 1.0), 16.0) * diffuse.a; light += (diffuse.rgb + light1spec) * lightcolor[1] * light1atten; } } vec3 light2dir = pos.xyz * lightpos[2].w - lightpos[2].xyz; float light2dist2 = dot(light2dir, light2dir); if(light2dist2 < 1.0) { float light2facing = dot(light2dir, normal.xyz); if(light2facing < 0.0) { float light2invdist = inversesqrt(light2dist2); float light2atten = light2facing * (1.0 - light2invdist); vec3 shadow2tc = getshadowtc(light2dir, shadowparams[2], shadowoffset[2], distbias * lightpos[2].w); light2atten *= filtershadow(shadow2tc); float light2spec = pow(clamp(light2invdist*(dot(camdir, light2dir) - light2facing*facing), 0.0, 1.0), 16.0) * diffuse.a; light += (diffuse.rgb + light2spec) * lightcolor[2] * light2atten; } } vec3 light3dir = pos.xyz * lightpos[3].w - lightpos[3].xyz; float light3dist2 = dot(light3dir, light3dir); if(light3dist2 < 1.0) { float light3facing = dot(light3dir, normal.xyz); if(light3facing < 0.0) { float light3invdist = inversesqrt(light3dist2); float light3atten = light3facing * (1.0 - light3invdist); vec3 shadow3tc = getshadowtc(light3dir, shadowparams[3], shadowoffset[3], distbias * lightpos[3].w); light3atten *= filtershadow(shadow3tc); float light3spec = pow(clamp(light3invdist*(dot(camdir, light3dir) - light3facing*facing), 0.0, 1.0), 16.0) * diffuse.a; light += (diffuse.rgb + light3spec) * lightcolor[3] * light3atten; } } vec3 light4dir = pos.xyz * lightpos[4].w - lightpos[4].xyz; float light4dist2 = dot(light4dir, light4dir); if(light4dist2 < 1.0) { float light4facing = dot(light4dir, normal.xyz); if(light4facing < 0.0) { float light4invdist = inversesqrt(light4dist2); float light4atten = light4facing * (1.0 - light4invdist); vec3 shadow4tc = getshadowtc(light4dir, shadowparams[4], shadowoffset[4], distbias * lightpos[4].w); light4atten *= filtershadow(shadow4tc); float light4spec = pow(clamp(light4invdist*(dot(camdir, light4dir) - light4facing*facing), 0.0, 1.0), 16.0) * diffuse.a; light += (diffuse.rgb + light4spec) * lightcolor[4] * light4atten; } } float foglerp = clamp(exp2(fogcoord*fogdensity.x)*fogdensity.y, 0.0, 1.0); accumlight(light*foglerp); accumalpha(0.0); }