From 93348abc18297dd1126b585f2bc30445baa6e1ff Mon Sep 17 00:00:00 2001 From: donkopunchstania Date: Sun, 19 Apr 2009 10:10:45 +0000 Subject: [PATCH] Created a free look utility which only works on win32 right now. It lets the user fly around with the mouse and keyboard. Had to add some ugly matrix functions to the math utilities. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3005 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/MathUtil.cpp | 105 ++++++++++++++++++ Source/Core/Common/Src/MathUtil.h | 32 ++++++ .../VideoCommon/Src/VertexShaderManager.cpp | 80 ++++++++++++- .../VideoCommon/Src/VertexShaderManager.h | 6 +- .../Plugin_VideoDX9/Src/VertexManager.cpp | 2 +- Source/Plugins/Plugin_VideoOGL/Src/Config.cpp | 2 + Source/Plugins/Plugin_VideoOGL/Src/Config.h | 1 + .../Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp | 19 +++- .../Plugin_VideoOGL/Src/GUI/ConfigDlg.h | 4 +- .../Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp | 64 +++++++++++ .../Plugin_VideoOGL/Src/VertexManager.cpp | 2 +- 11 files changed, 303 insertions(+), 14 deletions(-) diff --git a/Source/Core/Common/Src/MathUtil.cpp b/Source/Core/Common/Src/MathUtil.cpp index 65446cec0c..e2dbaa0640 100644 --- a/Source/Core/Common/Src/MathUtil.cpp +++ b/Source/Core/Common/Src/MathUtil.cpp @@ -20,6 +20,8 @@ #include "Common.h" #include "MathUtil.h" +#include + static u32 saved_sse_state = _mm_getcsr(); static const u32 default_sse_state = _mm_getcsr(); @@ -40,3 +42,106 @@ void SaveSSEState() { saved_sse_state = _mm_getcsr(); } + +void MatrixMul(int n, const float *a, const float *b, float *result) +{ + for(int i = 0; i < n; ++i) { + for(int j= 0; j < n; ++j) { + float temp = 0; + for(int k = 0; k < n; ++k) { + temp += a[i * n + k] * b[k * n + j]; + } + result[i * n + j] = temp; + } + } +} + +void Matrix33::LoadIdentity(Matrix33 &mtx) +{ + memset(mtx.data, 0, sizeof(mtx.data)); + mtx.data[0] = 1.0f; + mtx.data[4] = 1.0f; + mtx.data[8] = 1.0f; +} + +void Matrix33::RotateX(Matrix33 &mtx, float rad) +{ + float s = sin(rad); + float c = cos(rad); + memset(mtx.data, 0, sizeof(mtx.data)); + mtx.data[0] = 1; + mtx.data[4] = c; + mtx.data[5] = -s; + mtx.data[7] = s; + mtx.data[8] = c; +} +void Matrix33::RotateY(Matrix33 &mtx, float rad) +{ + float s = sin(rad); + float c = cos(rad); + memset(mtx.data, 0, sizeof(mtx.data)); + mtx.data[0] = c; + mtx.data[2] = s; + mtx.data[4] = 1; + mtx.data[6] = -s; + mtx.data[8] = c; +} + +void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result) +{ + MatrixMul(3, a.data, b.data, result.data); +} + +void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3]) +{ + for(int i = 0; i < 3; ++i) { + result[i] = 0; + for(int k = 0; k < 3; ++k) { + result[i] += a.data[i * 3 + k] * vec[k]; + } + } +} + +void Matrix44::LoadIdentity(Matrix44 &mtx) +{ + memset(mtx.data, 0, sizeof(mtx.data)); + mtx.data[0] = 1.0f; + mtx.data[5] = 1.0f; + mtx.data[10] = 1.0f; + mtx.data[15] = 1.0f; +} + +void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33) +{ + for(int i = 0; i < 3; ++i) { + for(int j = 0; j < 3; ++j) { + mtx.data[i * 4 + j] = m33.data[i * 3 + j]; + } + } + + for(int i = 0; i < 3; ++i) { + mtx.data[i * 4 + 3] = 0; + mtx.data[i + 12] = 0; + } + mtx.data[15] = 1.0f; +} + +void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16]) +{ + for(int i = 0; i < 16; ++i) { + mtx.data[i] = mtxArray[i]; + } +} + +void Matrix44::Translate(Matrix44 &mtx, const float vec[3]) +{ + LoadIdentity(mtx); + mtx.data[3] = vec[0]; + mtx.data[7] = vec[1]; + mtx.data[11] = vec[2]; +} + +void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result) +{ + MatrixMul(4, a.data, b.data, result.data); +} diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index cbf24bcd35..72c0eca29a 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -36,4 +36,36 @@ void LoadDefaultSSEState(); #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) +// ugly matrix implementation +class Matrix33 +{ +public: + static void LoadIdentity(Matrix33 &mtx); + + // set mtx to be a rotation matrix around the x axis + static void RotateX(Matrix33 &mtx, float rad); + // set mtx to be a rotation matrix around the y axis + static void RotateY(Matrix33 &mtx, float rad); + + // set result = a x b + static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result); + static void Multiply(const Matrix33 &a, const float vec[3], float result[3]); + + float data[9]; +}; + +class Matrix44 +{ +public: + static void LoadIdentity(Matrix44 &mtx); + static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33); + static void Set(Matrix44 &mtx, const float mtxArray[16]); + + static void Translate(Matrix44 &mtx, const float vec[3]); + + static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result); + + float data[16]; +}; + #endif // _MATH_UTIL_H_ diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp index 6e37e7b44b..3e6db1acbf 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "Common.h" +#include "MathUtil.h" #include "Profiler.h" #include @@ -45,6 +46,11 @@ static int nNormalMatricesChanged[2]; // min,max static int nPostTransformMatricesChanged[2]; // min,max static int nLightsChanged[2]; // min,max +static Matrix33 s_viewRotationMatrix; +static Matrix33 s_viewInvRotationMatrix; +static float s_fViewTranslationVector[3]; +static float s_fViewRotation[2]; + void UpdateViewport(); void VertexShaderManager::Init() @@ -59,6 +65,8 @@ void VertexShaderManager::Init() memset(&xfregs, 0, sizeof(xfregs)); memset(xfmem, 0, sizeof(xfmem)); + + ResetView(); } void VertexShaderManager::Shutdown() @@ -69,7 +77,7 @@ void VertexShaderManager::Shutdown() // ======================================================================================= // Syncs the shader constant buffers with xfmem // ---------------- -void VertexShaderManager::SetConstants(bool proj_hax_1,bool SMG_hack) +void VertexShaderManager::SetConstants(bool proj_hax_1,bool SMG_hack, bool freeLook) { //nTransformMatricesChanged[0] = 0; nTransformMatricesChanged[1] = 256; //nNormalMatricesChanged[0] = 0; nNormalMatricesChanged[1] = 96; @@ -293,10 +301,29 @@ void VertexShaderManager::SetConstants(bool proj_hax_1,bool SMG_hack) } PRIM_LOG("Projection: %f %f %f %f %f %f\n", xfregs.rawProjection[0], xfregs.rawProjection[1], xfregs.rawProjection[2], xfregs.rawProjection[3], xfregs.rawProjection[4], xfregs.rawProjection[5]); - SetVSConstant4fv(C_PROJECTION, &g_fProjectionMatrix[0]); - SetVSConstant4fv(C_PROJECTION+1, &g_fProjectionMatrix[4]); - SetVSConstant4fv(C_PROJECTION+2, &g_fProjectionMatrix[8]); - SetVSConstant4fv(C_PROJECTION+3, &g_fProjectionMatrix[12]); + + if (freeLook) { + Matrix44 mtxA; + Matrix44 mtxB; + Matrix44 viewMtx; + + Matrix44::Translate(mtxA, s_fViewTranslationVector); + Matrix44::LoadMatrix33(mtxB, s_viewRotationMatrix); + Matrix44::Multiply(mtxB, mtxA, viewMtx); // view = rotation x translation + Matrix44::Set(mtxB, g_fProjectionMatrix); + Matrix44::Multiply(mtxB, viewMtx, mtxA); // mtxA = projection x view + + SetVSConstant4fv(C_PROJECTION, &mtxA.data[0]); + SetVSConstant4fv(C_PROJECTION+1, &mtxA.data[4]); + SetVSConstant4fv(C_PROJECTION+2, &mtxA.data[8]); + SetVSConstant4fv(C_PROJECTION+3, &mtxA.data[12]); + } + else { + SetVSConstant4fv(C_PROJECTION, &g_fProjectionMatrix[0]); + SetVSConstant4fv(C_PROJECTION+1, &g_fProjectionMatrix[4]); + SetVSConstant4fv(C_PROJECTION+2, &g_fProjectionMatrix[8]); + SetVSConstant4fv(C_PROJECTION+3, &g_fProjectionMatrix[12]); + } } } @@ -430,3 +457,46 @@ void VertexShaderManager::SetMaterialColor(int index, u32 data) s_fMaterials[ind++] = ((data>>8)&0xFF)/255.0f; s_fMaterials[ind] = ((data)&0xFF)/255.0f; } + +void VertexShaderManager::TranslateView(float x, float y) +{ + float result[3]; + float vector[3] = { x,0,y }; + + Matrix33::Multiply(s_viewInvRotationMatrix, vector, result); + + for(int i = 0; i < 3; i++) { + s_fViewTranslationVector[i] += result[i]; + } + + bProjectionChanged = true; +} + +void VertexShaderManager::RotateView(float x, float y) +{ + s_fViewRotation[0] += x; + s_fViewRotation[1] += y; + + Matrix33 mx; + Matrix33 my; + Matrix33::RotateX(mx, s_fViewRotation[1]); + Matrix33::RotateY(my, s_fViewRotation[0]); + Matrix33::Multiply(mx, my, s_viewRotationMatrix); + + // reverse rotation + Matrix33::RotateX(mx, -s_fViewRotation[1]); + Matrix33::RotateY(my, -s_fViewRotation[0]); + Matrix33::Multiply(my, mx, s_viewInvRotationMatrix); + + bProjectionChanged = true; +} + +void VertexShaderManager::ResetView() +{ + memset(s_fViewTranslationVector, 0, sizeof(s_fViewTranslationVector)); + Matrix33::LoadIdentity(s_viewRotationMatrix); + Matrix33::LoadIdentity(s_viewInvRotationMatrix); + s_fViewRotation[0] = s_fViewRotation[1] = 0.0f; + + bProjectionChanged = true; +} diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.h b/Source/Core/VideoCommon/Src/VertexShaderManager.h index dc7ecd2706..8bb3f3d455 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderManager.h +++ b/Source/Core/VideoCommon/Src/VertexShaderManager.h @@ -28,7 +28,7 @@ public: static void Shutdown(); // constant management - static void SetConstants(bool proj_hax_1, bool SMG_hack); + static void SetConstants(bool proj_hax_1, bool SMG_hack, bool freeLook); static void SetViewport(float* _Viewport); static void SetViewportChanged(); @@ -37,6 +37,10 @@ public: static void SetTexMatrixChangedA(u32 Value); static void SetTexMatrixChangedB(u32 Value); static void SetMaterialColor(int index, u32 data); + + static void TranslateView(float x, float y); + static void RotateView(float x, float y); + static void ResetView(); }; void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index 394a02e3d5..d0b2b97618 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -235,7 +235,7 @@ void Flush() if (numVertices) { // set global constants - VertexShaderManager::SetConstants(false, false); + VertexShaderManager::SetConstants(false, false, false); PixelShaderManager::SetConstants(); PixelShaderCache::SetShader(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp index 9843215724..7f038a3d58 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp @@ -62,6 +62,7 @@ void Config::Load() iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0); iniFile.Get("Settings", "DumpEFBTarget", &bDumpEFBTarget, 0); iniFile.Get("Settings", "DumpFrames", &bDumpFrames, 0); + iniFile.Get("Settings", "FreeLook", &bFreeLook, 0); iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0); iniFile.Get("Settings", "MSAA", &iMultisampleMode, 0); iniFile.Get("Settings", "DstAlphaPass", &bDstAlphaPass, false); @@ -147,6 +148,7 @@ void Config::Save() iniFile.Set("Settings", "DumpTextures", bDumpTextures); iniFile.Set("Settings", "DumpEFBTarget", bDumpEFBTarget); iniFile.Set("Settings", "DumpFrames", bDumpFrames); + iniFile.Set("Settings", "FreeLook", bFreeLook); iniFile.Set("Settings", "ShowEFBCopyRegions", bShowEFBCopyRegions); iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors); iniFile.Set("Settings", "MSAA", iMultisampleMode); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Config.h b/Source/Plugins/Plugin_VideoOGL/Src/Config.h index 2b7450934b..5910adf5a0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Config.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/Config.h @@ -86,6 +86,7 @@ struct Config bool bDumpTextures; bool bDumpEFBTarget; bool bDumpFrames; + bool bFreeLook; // Hacks bool bEFBCopyDisable; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp index 66a055fa40..9b2cc92011 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp @@ -21,6 +21,7 @@ #include "../Config.h" #include "../TextureMngr.h" +#include "VertexShaderManager.h" BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) EVT_CLOSE(ConfigDialog::OnClose) @@ -54,7 +55,8 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) EVT_CHECKBOX(ID_TEXFMTCENTER, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DUMPTEXTURES, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DUMPEFBTARGET, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_DUMPFRAMES, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_DUMPFRAMES, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_FREELOOK, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DISABLELIGHTING, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DISABLETEXTURING, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DISABLEFOG, ConfigDialog::AdvancedSettingsChanged) @@ -350,6 +352,8 @@ void ConfigDialog::CreateGUIControls() " set up for the dump or several gigabytes of space available.")); #endif m_DumpFrames->SetValue(g_Config.bDumpFrames); + m_FreeLook = new wxCheckBox(m_PageAdvanced, ID_FREELOOK, wxT("Free Look"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_FreeLook->SetValue(g_Config.bFreeLook); // Hacks controls m_SafeTextureCache = new wxCheckBox(m_PageAdvanced, ID_SAFETEXTURECACHE, wxT("Use Safe texture cache"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); @@ -415,10 +419,12 @@ void ConfigDialog::CreateGUIControls() sRenderBoxRow1->Add(sSBox, 0, wxALL|wxEXPAND, 5); sbRendering->Add(sRenderBoxRow1); - sUtilities = new wxBoxSizer(wxHORIZONTAL); - sUtilities->Add(m_DumpTextures, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); - sUtilities->Add(m_DumpEFBTarget, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); - sUtilities->Add(m_DumpFrames, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + //sUtilities = new wxBoxSizer(wxHORIZONTAL); + sUtilities = new wxGridBagSizer(0, 0); + sUtilities->Add(m_DumpTextures, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sUtilities->Add(m_DumpEFBTarget, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sUtilities->Add(m_DumpFrames, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sUtilities->Add(m_FreeLook, wxGBPosition(1, 1), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); sbUtilities->Add(sUtilities, 1, wxEXPAND); // Sizers @@ -558,6 +564,9 @@ void ConfigDialog::AdvancedSettingsChanged(wxCommandEvent& event) case ID_DUMPFRAMES: g_Config.bDumpFrames = m_DumpFrames->IsChecked(); break; + case ID_FREELOOK: + g_Config.bFreeLook = m_FreeLook->IsChecked(); + break; case ID_TEXTUREPATH: break; case ID_CHECKBOX_DISABLECOPYEFB: diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.h b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.h index de3fc248fa..0b4ed94bd0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.h @@ -64,7 +64,7 @@ class ConfigDialog : public wxDialog wxStaticBoxSizer* sbRendering; wxGridBagSizer* sRendering; wxStaticBoxSizer* sbUtilities; - wxBoxSizer* sUtilities; + wxGridBagSizer* sUtilities; wxStaticBoxSizer* sbHacks; wxGridBagSizer* sHacks; @@ -108,6 +108,7 @@ class ConfigDialog : public wxDialog wxCheckBox *m_DumpTextures; wxCheckBox *m_DumpEFBTarget; wxCheckBox *m_DumpFrames; + wxCheckBox *m_FreeLook; wxStaticBox * m_StaticBox_EFB; wxCheckBox *m_CheckBox_DisableCopyEFB; wxRadioButton *m_Radio_CopyEFBToRAM, *m_Radio_CopyEFBToGL; @@ -167,6 +168,7 @@ class ConfigDialog : public wxDialog ID_DUMPTEXTURES, ID_DUMPEFBTARGET, ID_DUMPFRAMES, + ID_FREELOOK, ID_TEXTUREPATH, ID_CHECKBOX_DISABLECOPYEFB, diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp index 4c76c8b807..260651154e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp @@ -28,6 +28,7 @@ #include "main.h" #include "Win32.h" #include "OnScreenDisplay.h" +#include "VertexShaderManager.h" #include "StringUtil.h" @@ -138,6 +139,65 @@ HWND GetChildParentWnd() return m_hMain; } +void FreeLookInput( UINT iMsg, WPARAM wParam ) +{ + static float debugSpeed = 1.0f; + static bool mouseLookEnabled = false; + static float lastMouse[2]; + + switch( iMsg ) + { + + case WM_KEYDOWN: + switch( LOWORD( wParam )) + { + case '9': + debugSpeed /= 2.0f; + break; + case '0': + debugSpeed *= 2.0f; + break; + case 'W': + VertexShaderManager::TranslateView(0.0f, debugSpeed); + break; + case 'S': + VertexShaderManager::TranslateView(0.0f, -debugSpeed); + break; + case 'A': + VertexShaderManager::TranslateView(debugSpeed, 0.0f); + break; + case 'D': + VertexShaderManager::TranslateView(-debugSpeed, 0.0f); + break; + case 'R': + VertexShaderManager::ResetView(); + break; + } + break; + + case WM_MOUSEMOVE: + if (mouseLookEnabled) { + POINT point; + GetCursorPos(&point); + VertexShaderManager::RotateView((point.x - lastMouse[0]) / 200.0f, (point.y - lastMouse[1]) / 200.0f); + lastMouse[0] = point.x; + lastMouse[1] = point.y; + } + break; + + case WM_RBUTTONDOWN: + POINT point; + GetCursorPos(&point); + lastMouse[0] = point.x; + lastMouse[1] = point.y; + mouseLookEnabled= true; + break; + case WM_RBUTTONUP: + mouseLookEnabled = false; + break; + } +} + LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) { HDC hdc; @@ -298,6 +358,10 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) break; } + if (g_Config.bFreeLook) { + FreeLookInput( iMsg, wParam ); + } + return DefWindowProc(hWnd, iMsg, wParam, lParam); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index d313d70f8e..a5c920c64a 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -278,7 +278,7 @@ void Flush() Renderer::SetRenderMode(Renderer::RM_Normal); // set global constants - VertexShaderManager::SetConstants(g_Config.bProjectionHax1, g_Config.bSMGhack); + VertexShaderManager::SetConstants(g_Config.bProjectionHax1, g_Config.bSMGhack, g_Config.bFreeLook); PixelShaderManager::SetConstants(); // finally bind