diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 118e66f9d..d5af3ce7c 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -63,9 +63,18 @@ static const char iqm_frag[] = #include "iqm.fc" ; +typedef struct { + shaderparam_t position; + shaderparam_t color; +} lightpar_t; + +#define MAX_IQM_LIGHTS 8 +#define MAX_IQM_BONES 80 + static struct { int program; shaderparam_t mvp_matrix; + shaderparam_t norm_matrix; shaderparam_t bonemats; shaderparam_t vcolor; shaderparam_t vweights; @@ -74,10 +83,14 @@ static struct { shaderparam_t vtangent; shaderparam_t vnormal; shaderparam_t position; + lightpar_t lights[MAX_IQM_LIGHTS]; + shaderparam_t texture; + shaderparam_t normalmap; shaderparam_t fog; } iqm_shader = { 0, {"mvp_mat", 1}, + {"norm_mat", 1}, {"bonemats", 1}, {"vcolor", 0}, {"vweights", 0}, @@ -86,6 +99,18 @@ static struct { {"vtangent", 0}, {"vnormal", 0}, {"position", 0}, + { + {{"lights[0].position", 1}, {"lights[0].color", 1}}, + {{"lights[1].position", 1}, {"lights[1].color", 1}}, + {{"lights[2].position", 1}, {"lights[2].color", 1}}, + {{"lights[3].position", 1}, {"lights[3].color", 1}}, + {{"lights[4].position", 1}, {"lights[4].color", 1}}, + {{"lights[5].position", 1}, {"lights[5].color", 1}}, + {{"lights[6].position", 1}, {"lights[6].color", 1}}, + {{"lights[7].position", 1}, {"lights[7].color", 1}}, + }, + {"texture", 1}, + {"normalmap", 1}, {"fog", 1}, }; @@ -111,11 +136,13 @@ glsl_R_InitIQM (void) { int vert; int frag; + int i; vert = GLSL_CompileShader ("iqm.vert", iqm_vert, GL_VERTEX_SHADER); frag = GLSL_CompileShader ("iqm.frag", iqm_frag, 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); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.bonemats); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.vcolor); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.vweights); @@ -124,6 +151,14 @@ glsl_R_InitIQM (void) GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.vtangent); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.vnormal); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.position); + for (i = 0; i < MAX_IQM_LIGHTS; i++) { + GLSL_ResolveShaderParam (iqm_shader.program, + &iqm_shader.lights[i].position); + GLSL_ResolveShaderParam (iqm_shader.program, + &iqm_shader.lights[i].color); + } + GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.texture); + GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.normalmap); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.fog); } @@ -146,7 +181,8 @@ set_arrays (iqm_t *iqm) qfeglEnableVertexAttribArray (attr->attr->location); qfeglVertexAttribPointer (attr->attr->location, attr->size, attr->type, attr->normalized, iqm->stride, - (byte *) 0 + va->offset); + iqm->vertices + va->offset); + //(byte *) 0 + va->offset); } while (j <= IQM_COLOR) qfeglDisableVertexAttribArray (vertex_attribs[j++].attr->location); @@ -155,11 +191,66 @@ set_arrays (iqm_t *iqm) void glsl_R_DrawIQM (void) { + static quat_t color = { 1, 1, 1, 1}; entity_t *ent = currententity; model_t *model = ent->model; iqm_t *iqm = (iqm_t *) model->aliashdr; + dlight_t **lights; + int i; + vec_t norm_mat[9]; + mat4_t mvp_mat; + float blend; + iqmframe_t *frame; + Sys_MaskPrintf (SYS_GLSL, "glsl_R_DrawIQM\n"); + lights = R_FindNearLights (ent->origin, MAX_IQM_LIGHTS); + + // we need only the rotation for normals. + VectorCopy (ent->transform + 0, norm_mat + 0); + VectorCopy (ent->transform + 4, norm_mat + 3); + VectorCopy (ent->transform + 8, norm_mat + 6); + Mat4Mult (iqm_vp, ent->transform, mvp_mat); + + blend = R_EntityBlend (ent, ent->frame, 0.1); + + frame = malloc (iqm->num_joints * sizeof (iqmframe_t)); + for (i = 0; i < iqm->num_joints; i++) { + iqmframe_t *f1 = iqm->frames[ent->pose1]; + iqmframe_t *f2 = iqm->frames[ent->pose2]; + DualQuatBlend (f1->rt, f2->rt, blend, frame[i].rt); + QuatBlend (f1->shear, f2->shear, blend, frame[i].shear); + QuatBlend (f1->scale, f2->scale, blend, frame[i].scale); + } + + for (i = 0; i < MAX_IQM_LIGHTS; i++) { + quat_t val; + lightpar_t *l = &iqm_shader.lights[i]; + if (!lights[i]) + break; + VectorCopy (lights[i]->origin, val); + val[3] = lights[i]->radius; + qfeglUniform4fv (l->position.location, 1, val); + qfeglUniform4fv (l->color.location, 1, lights[i]->color); + } + for (; i < MAX_IQM_LIGHTS; i++) { + lightpar_t *l = &iqm_shader.lights[i]; + qfeglUniform4fv (l->position.location, 1, quat_origin); + qfeglUniform4fv (l->color.location, 1, quat_origin); + } + free (lights); + + qfeglUniformMatrix4fv (iqm_shader.mvp_matrix.location, 1, false, mvp_mat); + qfeglUniformMatrix3fv (iqm_shader.norm_matrix.location, 1, false, + norm_mat); + qfeglUniformMatrix4fv (iqm_shader.bonemats.location, iqm->num_joints, + false, (float *) frame); + qfeglVertexAttrib4fv (iqm_shader.vcolor.location, color); set_arrays (iqm); + for (i = 0; i < iqm->num_meshes; i++) { + qfeglDrawElements (GL_TRIANGLES, 3 * iqm->meshes[i].num_triangles, + GL_UNSIGNED_SHORT, + iqm->elements + 3 * iqm->meshes[i].first_triangle); + } } // All iqm models are drawn in a batch, so avoid thrashing the gl state diff --git a/libs/video/renderer/glsl/iqm.frag b/libs/video/renderer/glsl/iqm.frag index afc4a9016..b9eee598e 100644 --- a/libs/video/renderer/glsl/iqm.frag +++ b/libs/video/renderer/glsl/iqm.frag @@ -1,6 +1,10 @@ +struct light { + vec4 position; // xyz = pos, w = strength + vec4 color; // rgb. a = ? +}; uniform sampler2D texture; uniform sampler2D normalmap; -uniform vec4 lights[8]; +uniform light lights[8]; uniform vec4 fog; varying vec3 bitangent; @@ -29,28 +33,29 @@ vec3 calc_light (vec3 n, int ind) { vec3 d; + light l = lights[ind]; - d = lights[ind].xyz - gl_FragCoord.xyz; - return vec3 (lights[ind].w * dot (d, n) / dot (d, d)); + d = l.position.xyz - gl_FragCoord.xyz; + return l.color.rgb * (l.position.w * dot (d, n) / dot (d, d)); } void main (void) { mat3 tbn = mat3 (tangent, bitangent, normal); - vec3 norm, light; + vec3 norm, l; vec4 col; norm = texture2D (normalmap, st).xyz; norm = tbn * norm; - light += calc_light (norm, 0); - light += calc_light (norm, 1); - light += calc_light (norm, 2); - light += calc_light (norm, 3); - light += calc_light (norm, 4); - light += calc_light (norm, 5); - light += calc_light (norm, 6); - light += calc_light (norm, 7); - col = texture2D (texture, st) * color * vec4 (light, 1.0); + 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 index 9b515a150..d9b625510 100644 --- a/libs/video/renderer/glsl/iqm.vert +++ b/libs/video/renderer/glsl/iqm.vert @@ -1,4 +1,5 @@ uniform mat4 mvp_mat; +uniform mat3 norm_mat; uniform mat4 bonemats[80]; attribute vec4 vcolor; attribute vec4 vweights; @@ -49,9 +50,8 @@ main (void) t = vtangent.xyz; t += 2.0 * cross (q0.xyz, cross (q0.xyz, t) + q0.w * t); gl_Position = mvp_mat * vec4 (v, 1.0); - mat3 rot = mat3 (mvp_mat[0].xyz, mvp_mat[1].xyz, mvp_mat[3].xyz); - normal = rot * n; - tangent = rot * t; + normal = norm_mat * n; + tangent = norm_mat * t; bitangent = cross (normal, tangent) * vtangent.w; color = vcolor; st = texcoord;