diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 933108b6b..68321ae78 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -3,10 +3,8 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) -shader_src= quakeforge.glsl \ - iqm.frag iqm.vert -shader_gen= quakeforge.slc \ - iqm.fc iqm.vc +shader_src= quakeforge.glsl +shader_gen= quakeforge.slc glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index b8cae10bd..d189a4cbe 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -55,13 +55,19 @@ #include "r_internal.h" -static const char iqm_vert[] = -#include "iqm.vc" -; +static const char *iqm_vert_effects[] = +{ + "QuakeForge.Math.quaternion", + "QuakeForge.Vertex.iqm", + 0 +}; -static const char iqm_frag[] = -#include "iqm.fc" -; +static const char *iqm_frag_effects[] = +{ + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.iqm", + 0 +}; typedef struct { shaderparam_t position; @@ -136,12 +142,15 @@ static mat4_t iqm_vp; void glsl_R_InitIQM (void) { + shader_t *vert_shader, *frag_shader; int vert; int frag; int i; - vert = GLSL_CompileShaderS ("iqm.vert", iqm_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("iqm.frag", iqm_frag, GL_FRAGMENT_SHADER); + vert_shader = GLSL_BuildShader (iqm_vert_effects); + frag_shader = GLSL_BuildShader (iqm_frag_effects); + vert = GLSL_CompileShader ("iqm.vert", vert_shader, GL_VERTEX_SHADER); + frag = GLSL_CompileShader ("iqm.frag", frag_shader, GL_FRAGMENT_SHADER); iqm_shader.program = GLSL_LinkProgram ("iqm", vert, frag); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.mvp_matrix); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.norm_matrix); @@ -163,6 +172,8 @@ glsl_R_InitIQM (void) GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.texture); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.normalmap); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.fog); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); } static void diff --git a/libs/video/renderer/glsl/iqm.frag b/libs/video/renderer/glsl/iqm.frag deleted file mode 100644 index fd4b64b87..000000000 --- a/libs/video/renderer/glsl/iqm.frag +++ /dev/null @@ -1,67 +0,0 @@ -struct light { - vec4 position; // xyz = pos, w = strength - vec4 color; // rgb. a = ? -}; -uniform sampler2D texture; -uniform sampler2D normalmap; -uniform vec3 ambient; -uniform light lights[8]; -uniform vec4 fog; - -varying vec3 position; -varying vec3 bitangent; -varying vec3 tangent; -varying vec3 normal; -varying vec2 st; -varying vec4 color; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -vec3 -calc_light (vec3 n, int ind) -{ - vec3 d; - light l = lights[ind]; - float mag; - - d = l.position.xyz - position; - mag = dot (d, n); - mag = max (0.0, mag); - return l.color.rgb * (l.position.w * mag / dot (d, d)); -} - -void -main (void) -{ - mat3 tbn = mat3 (tangent, bitangent, normal); - vec3 norm, l; - vec4 col; - - norm = (texture2D (normalmap, st).xyz - vec3(0.5)) * 2.0; - norm = tbn * norm; - l = ambient; - l += calc_light (norm, 0); - l += calc_light (norm, 1); - l += calc_light (norm, 2); - l += calc_light (norm, 3); - l += calc_light (norm, 4); - l += calc_light (norm, 5); - l += calc_light (norm, 6); - l += calc_light (norm, 7); - col = texture2D (texture, st) * color * vec4 (l, 1.0); - gl_FragColor = fogBlend (col); -} diff --git a/libs/video/renderer/glsl/iqm.vert b/libs/video/renderer/glsl/iqm.vert deleted file mode 100644 index 180212e9f..000000000 --- a/libs/video/renderer/glsl/iqm.vert +++ /dev/null @@ -1,82 +0,0 @@ -uniform mat4 mvp_mat; -uniform mat3 norm_mat; -uniform mat4 bonemats[80]; -attribute vec4 vcolor; -attribute vec4 vweights; -attribute vec4 vbones; -attribute vec4 vtangent; -attribute vec3 vnormal; -attribute vec2 texcoord; -attribute vec3 vposition; - -varying vec3 position; -varying vec3 bitangent; -varying vec3 tangent; -varying vec3 normal; -varying vec2 st; -varying vec4 color; - -vec3 -qmult (vec4 q, vec3 v) -{ - float qs = q.w; - vec3 qv = q.xyz; - vec3 t = cross (qv, v); - return (qs * qs) * v + 2.0 * qs * t + dot (qv, v) * qv + cross (qv, t); -} - -vec3 -dqtrans (vec4 q0, vec4 qe) -{//2.0 * (q0.w * qe.xyz - qe.w * q0.xyz - cross (qe.xyz, q0.xyz)); - float qs = q0.w, Ts = qe.w; - vec3 qv = -q0.xyz, Tv = qe.xyz; - - return 2.0 * (Ts * qv + qs * Tv + cross (Tv, qv)); -} - -void -main (void) -{ - mat4 m; - vec4 q0, qe; - vec3 sh, sc, tr, v, n, t; - - m = bonemats[int (vbones.x)] * vweights.x; - m += bonemats[int (vbones.y)] * vweights.y; - m += bonemats[int (vbones.z)] * vweights.z; - m += bonemats[int (vbones.w)] * vweights.w; -#if 0 - q0 = m[0].yzwx; //swizzle for conversion betwen QF and GL - qe = m[1].yzwx; //swizzle for conversion betwen QF and GL - sh = m[2].xyz; - sc = m[3].xyz; - - // extract translation from dual quaternion - tr = dqtrans (q0, qe); - // apply rotation and translation - v = qmult (q0, vposition) + tr; - // apply shear - v.z += v.y * sh.z + v.x * sh.y; - v.y += v.x * sh.x; - // apply scale - v *= sc; - // rotate normal (won't bother with shear or scale: not super accurate, - // but probably good enough) - n = qmult (q0, vnormal); - // rotate tangent (won't bother with shear or scale: not super accurate, - // but probably good enough) - t = qmult (q0, vtangent.xyz); -#else - mat3 nm = mat3 (m[0].xyz, m[1].xyz, m[2].xyz); - v = (m * vec4 (vposition, 1.0)).xyz; - n = nm * vnormal; - t = nm * vtangent.xyz; -#endif - position = v; - normal = norm_mat * n; - tangent = norm_mat * t; - bitangent = cross (normal, tangent) * vtangent.w; - color = vcolor; - st = texcoord; - gl_Position = mvp_mat * vec4 (position, 1.0); -} diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index ff1fd57a2..8ac479219 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -8,7 +8,7 @@ const float E = 2.71828183; vec3 qmult (vec4 q, vec3 v) { - float qc = q.w; + float qs = q.w; vec3 qv = q.xyz; vec3 t = cross (qv, v); return (qs * qs) * v + 2.0 * qs * t + dot (qv, v) * qv + cross (qv, t); @@ -431,3 +431,123 @@ main (void) discard; gl_FragColor = palettedColor (pix) * color; } + +-- Vertex.iqm + +uniform mat4 mvp_mat; +uniform mat3 norm_mat; +uniform mat4 bonemats[80]; +attribute vec4 vcolor; +attribute vec4 vweights; +attribute vec4 vbones; +attribute vec4 vtangent; +attribute vec3 vnormal; +attribute vec2 texcoord; +attribute vec3 vposition; + +varying vec3 position; +varying vec3 bitangent; +varying vec3 tangent; +varying vec3 normal; +varying vec2 st; +varying vec4 color; + +void +main (void) +{ + mat4 m; + vec4 q0, qe; + vec3 sh, sc, tr, v, n, t; + + m = bonemats[int (vbones.x)] * vweights.x; + m += bonemats[int (vbones.y)] * vweights.y; + m += bonemats[int (vbones.z)] * vweights.z; + m += bonemats[int (vbones.w)] * vweights.w; +#if 0 + q0 = m[0].yzwx; //swizzle for conversion betwen QF and GL + qe = m[1].yzwx; //swizzle for conversion betwen QF and GL + sh = m[2].xyz; + sc = m[3].xyz; + + // extract translation from dual quaternion + tr = dqtrans (q0, qe); + // apply rotation and translation + v = qmult (q0, vposition) + tr; + // apply shear + v.z += v.y * sh.z + v.x * sh.y; + v.y += v.x * sh.x; + // apply scale + v *= sc; + // rotate normal (won't bother with shear or scale: not super accurate, + // but probably good enough) + n = qmult (q0, vnormal); + // rotate tangent (won't bother with shear or scale: not super accurate, + // but probably good enough) + t = qmult (q0, vtangent.xyz); +#else + mat3 nm = mat3 (m[0].xyz, m[1].xyz, m[2].xyz); + v = (m * vec4 (vposition, 1.0)).xyz; + n = nm * vnormal; + t = nm * vtangent.xyz; +#endif + position = v; + normal = norm_mat * n; + tangent = norm_mat * t; + bitangent = cross (normal, tangent) * vtangent.w; + color = vcolor; + st = texcoord; + gl_Position = mvp_mat * vec4 (position, 1.0); +} + +-- Fragment.iqm + +struct light { + vec4 position; // xyz = pos, w = strength + vec4 color; // rgb. a = ? +}; +uniform sampler2D texture; +uniform sampler2D normalmap; +uniform vec3 ambient; +uniform light lights[8]; + +varying vec3 position; +varying vec3 bitangent; +varying vec3 tangent; +varying vec3 normal; +varying vec2 st; +varying vec4 color; + +vec3 +calc_light (vec3 n, int ind) +{ + vec3 d; + light l = lights[ind]; + float mag; + + d = l.position.xyz - position; + mag = dot (d, n); + mag = max (0.0, mag); + return l.color.rgb * (l.position.w * mag / dot (d, d)); +} + +void +main (void) +{ + mat3 tbn = mat3 (tangent, bitangent, normal); + vec3 norm, l; + vec4 col; + + norm = (texture2D (normalmap, st).xyz - vec3(0.5)) * 2.0; + norm = tbn * norm; + l = ambient; + l += calc_light (norm, 0); + l += calc_light (norm, 1); + l += calc_light (norm, 2); + l += calc_light (norm, 3); + l += calc_light (norm, 4); + l += calc_light (norm, 5); + l += calc_light (norm, 6); + l += calc_light (norm, 7); + col = texture2D (texture, st) * color * vec4 (l, 1.0); + gl_FragColor = fogBlend (col); +}