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:
parent
10e91c5771
commit
21d6185e26
4 changed files with 160 additions and 2 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue