From 21d6185e265161cc9bcfa52579cd093bab5e2762 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 21 Apr 2015 20:08:55 +0000 Subject: [PATCH] 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 --- engine/common/com_mesh.c | 1 + engine/gl/gl_backend.c | 56 +++++++++++++++++++++++ engine/gl/gl_shader.c | 9 +++- engine/gl/gl_vidcommon.c | 96 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 160 insertions(+), 2 deletions(-) diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 4c6613762..9257f50b5 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -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; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 0501d5dac..4a59020a2 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -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<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<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 diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 2c541d081..ed50e57f1 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -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; diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 32446cd63..88bf6db18 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -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)