fix skeletal models in webgl by emulating mat3x4. also fixes lighting issues.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4855 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-04-21 20:08:55 +00:00
parent 10e91c5771
commit 21d6185e26
4 changed files with 160 additions and 2 deletions

View File

@ -1661,6 +1661,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
mesh->numvertexes = inf->numverts;
mesh->indexes = inf->ofs_indexes;
mesh->numindexes = inf->numindexes;
mesh->numbones = 0;
#ifndef SERVERONLY
mesh->colors4f_array[0] = inf->ofs_rgbaf;

View File

@ -734,10 +734,22 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend
qglVertexAttribPointer(VATTR_TNORMALS, 3, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->tvector.gl.addr);
break;
case VATTR_BONENUMS:
/*if (!shaderstate.sourcevbo->bonenums.gl.vbo && !shaderstate.sourcevbo->bonenums.gl.addr)
{
shaderstate.sha_attr &= ~(1u<<i);
qglDisableVertexAttribArray(i);
continue;
}*/
GL_SelectVBO(shaderstate.sourcevbo->bonenums.gl.vbo);
qglVertexAttribPointer(VATTR_BONENUMS, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, shaderstate.sourcevbo->bonenums.gl.addr);
break;
case VATTR_BONEWEIGHTS:
/*if (!shaderstate.sourcevbo->boneweights.gl.vbo && !shaderstate.sourcevbo->boneweights.gl.addr)
{
shaderstate.sha_attr &= ~(1u<<i);
qglDisableVertexAttribArray(i);
continue;
}*/
GL_SelectVBO(shaderstate.sourcevbo->boneweights.gl.vbo);
qglVertexAttribPointer(VATTR_BONEWEIGHTS, 4, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->boneweights.gl.addr);
break;
@ -3048,7 +3060,12 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
break;
case SP_M_ENTBONES:
{
#ifdef GLESONLY
//cop out.
qglUniform4fvARB(ph, shaderstate.sourcevbo->numbones*3, shaderstate.sourcevbo->bones);
#else
qglUniformMatrix3x4fv(ph, shaderstate.sourcevbo->numbones, false, shaderstate.sourcevbo->bones);
#endif
}
break;
case SP_M_INVVIEWPROJECTION:
@ -4183,6 +4200,45 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m)
shaderstate.colourarraytype = GL_FLOAT;
}
if (m->normals_array)
{
memcpy(buffer+len, m->normals_array, sizeof(*m->normals_array) * m->numvertexes);
shaderstate.dummyvbo.normals.gl.addr = (void*)len;
shaderstate.dummyvbo.normals.gl.vbo = shaderstate.streamvbo[shaderstate.streamid];
len += sizeof(*m->normals_array) * m->numvertexes;
}
else
{
shaderstate.dummyvbo.normals.gl.addr = NULL;
shaderstate.dummyvbo.normals.gl.vbo = 0;
}
if (m->bonenums)
{
memcpy(buffer+len, m->bonenums, sizeof(*m->bonenums) * m->numvertexes);
shaderstate.dummyvbo.bonenums.gl.addr = (void*)len;
shaderstate.dummyvbo.bonenums.gl.vbo = shaderstate.streamvbo[shaderstate.streamid];
len += sizeof(*m->bonenums) * m->numvertexes;
}
else
{
shaderstate.dummyvbo.bonenums.gl.addr = NULL;
shaderstate.dummyvbo.bonenums.gl.vbo = 0;
}
if (m->boneweights)
{
memcpy(buffer+len, m->boneweights, sizeof(*m->boneweights) * m->numvertexes);
shaderstate.dummyvbo.boneweights.gl.addr = (void*)len;
shaderstate.dummyvbo.boneweights.gl.vbo = shaderstate.streamvbo[shaderstate.streamid];
len += sizeof(*m->boneweights) * m->numvertexes;
}
else
{
shaderstate.dummyvbo.boneweights.gl.addr = NULL;
shaderstate.dummyvbo.boneweights.gl.vbo = 0;
}
//FIXME: normals, svector, tvector, bone nums, bone weights
//now we've got a single buffer in a single place, update the buffer

View File

@ -3634,7 +3634,7 @@ void Shader_Programify (shader_t *s)
T_MODEL
} type = 0;*/
int i;
shaderpass_t *pass, *lightmap = NULL, *modellighting = NULL;
shaderpass_t *pass, *lightmap = NULL, *modellighting = NULL, *vertexlighting = NULL;
for (i = 0; i < s->numpasses; i++)
{
pass = &s->passes[i];
@ -3642,6 +3642,8 @@ void Shader_Programify (shader_t *s)
modellighting = pass;
else if (pass->rgbgen == RGB_GEN_ENTITY)
modellighting = pass;
else if (pass->rgbgen == RGB_GEN_VERTEX_LIGHTING || pass->rgbgen == RGB_GEN_VERTEX_EXACT)
vertexlighting = pass;
else if (pass->texgen == T_GEN_LIGHTMAP && pass->tcgen == TC_GEN_LIGHTMAP)
lightmap = pass;
}
@ -3656,6 +3658,11 @@ void Shader_Programify (shader_t *s)
pass = modellighting;
prog = "defaultwall";
}
else if (vertexlighting)
{
pass = vertexlighting;
prog = "default2d";
}
else
{
pass = NULL;

View File

@ -1180,7 +1180,11 @@ static const char *glsl_hdrs[] =
"};\n"
"layout(std140) unform u_bones\n"
"{\n"
#ifdef GLESONLY
"vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n"
#else
"mat3x4 m_bones["STRINGIFY(MAX_GPU_BONES)"]\n"
#endif
"};\n"
"#else\n"
"uniform mat4 m_model;\n"
@ -1188,7 +1192,11 @@ static const char *glsl_hdrs[] =
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
// "uniform mat4 m_modelviewprojection;\n"
#ifdef GLESONLY
"uniform vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n"
#else
"uniform mat4 m_bones["STRINGIFY(MAX_GPU_BONES)"];\n"
#endif
"uniform mat4 m_invviewprojection;\n"
"uniform mat4 m_invmodelviewprojection;\n"
@ -1242,20 +1250,62 @@ static const char *glsl_hdrs[] =
"#ifndef DEFS_DEFINED\n"
"attribute vec4 v_bone;"
"attribute vec4 v_weight;"
#ifdef GLESONLY
"uniform vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n"
#else
"uniform mat3x4 m_bones["STRINGIFY(MAX_GPU_BONES)"];\n"
#endif
"#endif\n"
"vec4 skeletaltransform()"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;\n"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;\n"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;\n"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;\n"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
#endif
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
"b = (vec4(v_tvector.xyz, 0.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
@ -1265,9 +1315,31 @@ static const char *glsl_hdrs[] =
"t = vec4(v_svector.xyz, 0.0) * wmat;"
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
#endif
"}\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
"b = (vec4(v_tvector.xyz, 0.0) * wmat).xyz;"
"w = (vec4(v_position.xyz, 1.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
@ -1278,9 +1350,28 @@ static const char *glsl_hdrs[] =
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"w = vec4(v_position.xyz, 1.0) * wmat;"
"return m_modelviewprojection * vec4(w, 1.0);"
#endif
"}\n"
"vec4 skeletaltransform_n(out vec3 n)"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
@ -1288,6 +1379,7 @@ static const char *glsl_hdrs[] =
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
#endif
"}\n"
"#else\n"
"#define skeletaltransform() ftetransform()\n"
@ -1622,7 +1714,7 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
if (ver > gl_config.maxglslversion)
return 0;
#ifdef FTE_TARGET_WEB
//emscripten prefixes our shader with a precision specifier, and then the browser bitches as the (otherwise valid) #version, so don't say anything at all if its ver 100, and the browser won't complain
//emscripten prefixes our shader with a precision specifier, and then the browser bitches at the following (otherwise valid) #version, so don't say anything at all if its ver 100, and the browser won't complain
if (ver != 100)
#endif
{
@ -2037,8 +2129,10 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned
if (!ver)
{
ver = gl_config.gles?100:110;
#ifndef GLESONLY
if (permu & PERMUTATION_SKELETAL)
ver = 120;
#endif
}
prog->permu[permu].handle = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, tcs, tes, frag, noerrors, blobfile);
if (prog->permu[permu].handle.glsl.handle)