diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index dc95d295f7..6ce57a7b89 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -148,6 +148,7 @@ void GenerateFragmentShader(char *buffer) { char *p = buffer; #if defined(GLSL_ES_1_0) + WRITE(p, "#version 100\n"); // GLSL ES 1.0 WRITE(p, "precision lowp float;\n"); #elif !defined(FORCE_OPENGL_2_0) WRITE(p, "#version 110\n"); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 57fc10a058..51bb5e6130 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -105,8 +105,16 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs) u_view = glGetUniformLocation(program, "u_view"); u_world = glGetUniformLocation(program, "u_world"); u_texmtx = glGetUniformLocation(program, "u_texmtx"); - u_bone = glGetUniformLocation(program, "u_bone"); numBones = gstate.getNumBoneWeights(); +#ifdef USE_BONE_ARRAY + u_bone = glGetUniformLocation(program, "u_bone"); +#else + for (int i = 0; i < numBones; i++) { + char name[10]; + sprintf(name, "u_bone%i", i); + u_bone[i] = glGetUniformLocation(program, name); + } +#endif // Lighting, texturing u_ambient = glGetUniformLocation(program, "u_ambient"); @@ -323,6 +331,7 @@ void LinkedShader::updateUniforms() { } // TODO: Could even set all bones in one go if they're all dirty. +#ifdef USE_BONE_ARRAY if (u_bone != -1) { float allBones[8 * 16]; @@ -346,6 +355,15 @@ void LinkedShader::updateUniforms() { } } } +#else + float bonetemp[16]; + for (int i = 0; i < numBones; i++) { + if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { + ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, bonetemp); + glUniformMatrix4fv(u_bone[i], 1, GL_FALSE, bonetemp); + } + } +#endif // Lighting if (u_ambient != -1 && (dirtyUniforms & DIRTY_AMBIENT)) { diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index b4a7fdf25a..6d7fac8fb7 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -54,7 +54,11 @@ public: int u_view; int u_texmtx; int u_world; +#ifdef USE_BONE_ARRAY int u_bone; // array, size is numBones +#else + int u_bone[8]; +#endif int numBones; // Fragment processing inputs diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 39d66e6bfa..b3fae68602 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -128,6 +128,7 @@ void GenerateVertexShader(int prim, char *buffer) { // #define USE_FOR_LOOP #if defined(USING_GLES2) + WRITE(p, "#version 100\n"); // GLSL ES 1.0 WRITE(p, "precision highp float;\n"); #elif !defined(FORCE_OPENGL_2_0) @@ -213,7 +214,13 @@ void GenerateVertexShader(int prim, char *buffer) { WRITE(p, "uniform mediump mat4 u_texmtx;\n"); if ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { int numBones = 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); +#ifdef USE_BONE_ARRAY WRITE(p, "uniform mediump mat4 u_bone[%i];\n", numBones); +#else + for (int i = 0; i < numBones; i++) { + WRITE(p, "uniform mediump mat4 u_bone%i;\n", i); + } +#endif } for (int i = 0; i < 4; i++) { if (doLight[i] != LIGHT_OFF) { @@ -303,7 +310,7 @@ void GenerateVertexShader(int prim, char *buffer) { "a_w2.x", "a_w2.y", "a_w2.z", "a_w2.w", }; -#ifdef USE_FOR_LOOP +#if defined(USE_FOR_LOOP) && defined(USE_BONE_ARRAY) // To loop through the weights, we unfortunately need to put them in a float array. // GLSL ES sucks - no way to directly initialize an array! @@ -326,6 +333,8 @@ void GenerateVertexShader(int prim, char *buffer) { } #else + +#ifdef USE_BONE_ARRAY if (numWeights == 1) WRITE(p, " mat4 skinMatrix = a_w1 * u_bone[0]"); else @@ -337,9 +346,24 @@ void GenerateVertexShader(int prim, char *buffer) { if (numWeights == 5 && i == 4) weightAttr = "a_w2"; WRITE(p, " + %s * u_bone[%i]", weightAttr, i); } - WRITE(p, ";\n"); +#else + if (numWeights == 1) + WRITE(p, " mat4 skinMatrix = a_w1 * u_bone0"); + else + WRITE(p, " mat4 skinMatrix = a_w1.x * u_bone0"); + for (int i = 1; i < numWeights; i++) { + const char *weightAttr = boneWeightAttr[i]; + // workaround for "cant do .x of scalar" issue + if (numWeights == 1 && i == 0) weightAttr = "a_w1"; + if (numWeights == 5 && i == 4) weightAttr = "a_w2"; + WRITE(p, " + %s * u_bone%i", weightAttr, i); + } #endif +#endif + + WRITE(p, ";\n"); + // Trying to simplify this results in bugs in LBP... WRITE(p, " vec3 skinnedpos = (skinMatrix * vec4(a_position, 1.0)).xyz * %f;\n", factor); WRITE(p, " vec3 worldpos = (u_world * vec4(skinnedpos, 1.0)).xyz;\n"); diff --git a/GPU/GLES/VertexShaderGenerator.h b/GPU/GLES/VertexShaderGenerator.h index 06e0487e94..497b499b55 100644 --- a/GPU/GLES/VertexShaderGenerator.h +++ b/GPU/GLES/VertexShaderGenerator.h @@ -19,6 +19,8 @@ #include "Globals.h" +// #define USE_BONE_ARRAY + struct VertexShaderID { VertexShaderID() {d[0] = 0xFFFFFFFF;} diff --git a/lang b/lang index ee757b7684..09cd7ef7e6 160000 --- a/lang +++ b/lang @@ -1 +1 @@ -Subproject commit ee757b76849a885445acdfa7ae54ae1446dadf63 +Subproject commit 09cd7ef7e6da8ba09835630eb35d6b7f7e3e1664