diff --git a/Core/Config.cpp b/Core/Config.cpp index befe00334f..135d0a26eb 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -57,6 +57,7 @@ void CConfig::Load(const char *iniFileName) graphics->Get("DisplayFramebuffer", &bDisplayFramebuffer, false); graphics->Get("WindowZoom", &iWindowZoom, 1); graphics->Get("BufferedRendering", &bBufferedRendering, true); + graphics->Get("HardwareTransform", &bHardwareTransform, false); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Get("Enable", &bEnableSound, true); @@ -93,6 +94,7 @@ void CConfig::Save() graphics->Set("DisplayFramebuffer", bDisplayFramebuffer); graphics->Set("WindowZoom", iWindowZoom); graphics->Set("BufferedRendering", bBufferedRendering); + graphics->Set("HardwareTransform", bHardwareTransform); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Set("Enable", bEnableSound); diff --git a/Core/Config.h b/Core/Config.h index 461859e4aa..240b0fddb7 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -41,7 +41,10 @@ public: bool bSpeedLimit; bool bConfirmOnQuit; bool bIgnoreBadMemAccess; + + // GFX bool bDisplayFramebuffer; + bool bHardwareTransform; bool bBufferedRendering; bool bDrawWireframe; diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index e86db1dc34..41ac53c8e3 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -153,6 +153,27 @@ static void SetColorUniform3ExtraFloat(int uniform, u32 color, float extra) glUniform4fv(uniform, 1, col); } +static void SetMatrix4x3(int uniform, const float *m4x3) { + float m4x4[16]; + m4x4[0] = m4x3[0]; + m4x4[1] = m4x3[1]; + m4x4[2] = m4x3[2]; + m4x4[3] = 0.0f; + m4x4[4] = m4x3[3]; + m4x4[5] = m4x3[4]; + m4x4[6] = m4x3[5]; + m4x4[7] = 0.0f; + m4x4[8] = m4x3[6]; + m4x4[9] = m4x3[7]; + m4x4[10] = m4x3[8]; + m4x4[11] = 0.0f; + m4x4[12] = m4x3[9]; + m4x4[13] = m4x3[10]; + m4x4[14] = m4x3[11]; + m4x4[15] = 1.0f; + glUniformMatrix4fv(uniform, 1, GL_FALSE, m4x4); +} + void LinkedShader::use() { glUseProgram(program); glUniform1i(u_tex, 0); @@ -203,17 +224,17 @@ void LinkedShader::use() { // Transform if (u_world != -1 && (dirtyUniforms & DIRTY_WORLDMATRIX)) { - glUniformMatrix4x3fv(u_world, 1, GL_FALSE, gstate.worldMatrix); + SetMatrix4x3(u_world, gstate.worldMatrix); } if (u_view != -1 && (dirtyUniforms & DIRTY_VIEWMATRIX)) { - glUniformMatrix4x3fv(u_view, 1, GL_FALSE, gstate.viewMatrix); + SetMatrix4x3(u_view, gstate.viewMatrix); } if (u_texmtx != -1 && (dirtyUniforms & DIRTY_TEXMATRIX)) { - glUniformMatrix4x3fv(u_texmtx, 1, GL_FALSE, gstate.tgenMatrix); + SetMatrix4x3(u_texmtx, gstate.tgenMatrix); } for (int i = 0; i < 8; i++) { if (u_bone[i] != -1 && (dirtyUniforms & (DIRTY_BONEMATRIX0 << i))) { - glUniformMatrix4x3fv(u_bone[i], 1, GL_FALSE, gstate.boneMatrix + 12 * i); + SetMatrix4x3(u_bone[i], gstate.boneMatrix + 12 * i); } } diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 5021255f88..77276b76d9 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -26,6 +26,7 @@ #include "../ge_constants.h" #include "../GPUState.h" +#include "../../Core/Config.h" #include "VertexShaderGenerator.h" @@ -44,8 +45,9 @@ static char buffer[16384]; bool CanUseHardwareTransform(int prim) { - return !gstate.isModeThrough() && false; // prim != GE_PRIM_RECTANGLES; - //return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES; + if (!g_Config.bHardwareTransform) + return false; + return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES; } // prim so we can special case for RECTANGLES :( @@ -192,16 +194,16 @@ char *GenerateVertexShader(int prim) if (hwXForm) { // When transforming by hardware, we need a great deal more uniforms... - WRITE(p, "uniform mat4x3 u_world;\n"); - WRITE(p, "uniform mat4x3 u_view;\n"); + WRITE(p, "uniform mat4 u_world;\n"); + WRITE(p, "uniform mat4 u_view;\n"); if (gstate.getUVGenMode() == 0) WRITE(p, "uniform vec4 u_uvscaleoffset;\n"); else if (gstate.getUVGenMode() == 1) - WRITE(p, "uniform mat4x3 u_texmtx;\n"); + WRITE(p, "uniform mat4 u_texmtx;\n"); if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { int numBones = 1 + ((gstate.vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); for (int i = 0; i < numBones; i++) { - WRITE(p, "uniform mat4x3 u_bone%i;\n", i); + WRITE(p, "uniform mat4 u_bone%i;\n", i); } } if (gstate.lightingEnable & 1) { @@ -258,9 +260,9 @@ char *GenerateVertexShader(int prim) // Step 1: World Transform / Skinning if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { // No skinning, just standard T&L. - WRITE(p, " vec3 worldpos = u_world * vec4(a_position, 1.0);\n"); + WRITE(p, " vec3 worldpos = (u_world * vec4(a_position, 1.0)).xyz;\n"); if (hasNormal) - WRITE(p, " vec3 worldnormal = normalize(u_world * vec4(a_normal, 0.0));\n"); + WRITE(p, " vec3 worldnormal = (u_world * vec4(a_normal, 0.0)).xyz;\n"); } else { WRITE(p, " vec3 worldpos = vec3(0.0, 0.0, 0.0);\n"); if (hasNormal) @@ -271,15 +273,17 @@ char *GenerateVertexShader(int prim) // workaround for "cant do .x of scalar" issue if (numWeights == 1 && i == 0) weightAttr = "a_weight0123"; if (numWeights == 5 && i == 4) weightAttr = "a_weight4567"; - WRITE(p, " worldpos += %s * (u_bone%i * vec4(a_position, 1.0));\n", weightAttr, i); + WRITE(p, " worldpos += %s * (u_bone%i * vec4(a_position, 1.0)).xyz;\n", weightAttr, i); if (hasNormal) - WRITE(p, " worldnormal += %s * (u_bone%i * vec4(a_normal, 0.0));\n", weightAttr, i); + WRITE(p, " worldnormal += %s * (u_bone%i * vec4(a_normal, 0.0)).xyz;\n", weightAttr, i); } // Finally, multiply by world matrix (yes, we have to). - WRITE(p, " worldpos = u_world * vec4(worldpos, 1.0);\n"); + WRITE(p, " worldpos = (u_world * vec4(worldpos, 1.0)).xyz;\n"); if (hasNormal) - WRITE(p, " worldnormal = u_world * vec4(worldnormal, 0.0);\n"); + WRITE(p, " worldnormal = (u_world * vec4(worldnormal, 0.0)).xyz;\n"); } + if (hasNormal) + WRITE(p, " worldnormal = normalize(worldnormal);\n"); // Step 2: Color/Lighting if (hasColor) { @@ -395,7 +399,7 @@ char *GenerateVertexShader(int prim) } } // Step 4: Final view and projection transforms. - WRITE(p, " gl_Position = u_proj * vec4(u_view * vec4(worldpos, 1.0), 1.0);\n"); + WRITE(p, " gl_Position = u_proj * (u_view * vec4(worldpos, 1.0));\n"); } if (gstate.isFogEnabled()) WRITE(p, " v_depth = gl_Position.z;\n"); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 51664cc983..9146e38696 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -353,6 +353,11 @@ namespace MainWindow UpdateMenus(); break; + case ID_OPTIONS_HARDWARETRANSFORM: + g_Config.bHardwareTransform = !g_Config.bHardwareTransform; + UpdateMenus(); + break; + case ID_FILE_EXIT: DestroyWindow(hWnd); break; @@ -632,6 +637,7 @@ namespace MainWindow CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering); CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe); + CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform); BOOL enable = !Core_IsStepping(); EnableMenuItem(menu,ID_EMULATION_RUN,enable); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 4d12eb0163..70e0d2bd13 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -214,6 +214,7 @@ BEGIN MENUITEM "&Toggle Full Screen\tF12", ID_OPTIONS_FULLSCREEN MENUITEM "&Display Raw Framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER MENUITEM "&Buffered Rendering\tF5", ID_OPTIONS_BUFFEREDRENDERING + MENUITEM "&Hardware Transform", ID_OPTIONS_HARDWARETRANSFORM MENUITEM "&Wireframe (experimental)", ID_OPTIONS_WIREFRAME MENUITEM "&Show Debug Statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS MENUITEM SEPARATOR diff --git a/Windows/resource.h b/Windows/resource.h index 631760dffe..fbaf91b309 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -244,13 +244,14 @@ #define ID_CPU_FASTINTERPRETER 40121 #define ID_OPTIONS_SHOWDEBUGSTATISTICS 40122 #define ID_OPTIONS_WIREFRAME 40123 +#define ID_OPTIONS_HARDWARETRANSFORM 40124 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 232 -#define _APS_NEXT_COMMAND_VALUE 40124 +#define _APS_NEXT_COMMAND_VALUE 40125 #define _APS_NEXT_CONTROL_VALUE 1162 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/android/jni/MenuScreens.cpp b/android/jni/MenuScreens.cpp index 6cdbd87488..8052c357ca 100644 --- a/android/jni/MenuScreens.cpp +++ b/android/jni/MenuScreens.cpp @@ -241,7 +241,7 @@ void SettingsScreen::render() { int y = 50; UICheckBox(GEN_ID, x, y += 50, "Enable Sound Emulation", ALIGN_TOPLEFT, &g_Config.bEnableSound); UICheckBox(GEN_ID, x, y += 50, "Buffered Rendering (may fix flicker)", ALIGN_TOPLEFT, &g_Config.bBufferedRendering); - + UICheckBox(GEN_ID, x, y += 50, "Hardware Transform (experimental)", ALIGN_TOPLEFT, &g_Config.bHardwareTransform); bool useFastInt = g_Config.iCpuCore == CPU_FASTINTERPRETER; UICheckBox(GEN_ID, x, y += 50, "Slightly faster interpreter (may crash)", ALIGN_TOPLEFT, &useFastInt);