Use the new shader system for iqm models.

This commit is contained in:
Bill Currie 2014-01-28 13:28:35 +09:00
parent 385175ca65
commit 57d2198140
5 changed files with 142 additions and 162 deletions

View file

@ -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 \

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}