diff --git a/Source/Core/Common/MathUtil.cpp b/Source/Core/Common/MathUtil.cpp index e409e3fe24..05822dac77 100644 --- a/Source/Core/Common/MathUtil.cpp +++ b/Source/Core/Common/MathUtil.cpp @@ -351,6 +351,13 @@ void Matrix44::Translate(Matrix44 &mtx, const float vec[3]) mtx.data[11] = vec[2]; } +void Matrix44::Shear(Matrix44 &mtx, const float a, const float b) +{ + LoadIdentity(mtx); + mtx.data[2] = a; + mtx.data[6] = b; +} + 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/MathUtil.h b/Source/Core/Common/MathUtil.h index 5af6ce40f9..13ef25e647 100644 --- a/Source/Core/Common/MathUtil.h +++ b/Source/Core/Common/MathUtil.h @@ -232,6 +232,7 @@ public: static void Set(Matrix44 &mtx, const float mtxArray[16]); static void Translate(Matrix44 &mtx, const float vec[3]); + static void Shear(Matrix44 &mtx, const float a, const float b = 0); static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result); diff --git a/Source/Core/VideoCommon/ConstantManager.h b/Source/Core/VideoCommon/ConstantManager.h index 3e52640ca9..1c3ad55778 100644 --- a/Source/Core/VideoCommon/ConstantManager.h +++ b/Source/Core/VideoCommon/ConstantManager.h @@ -43,5 +43,6 @@ struct VertexShaderConstants float4 normalmatrices[32]; float4 posttransformmatrices[64]; float4 depthparams; + float4 stereoprojection[8]; }; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 991189a27f..9f1b5b69b4 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -51,7 +51,7 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy out.Write("%s", s_lighting_struct); // uniforms - /*if (ApiType == API_OPENGL) + if (ApiType == API_OPENGL) out.Write("layout(std140%s) uniform VSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : ""); else out.Write("cbuffer VSBlock {\n"); @@ -65,7 +65,8 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy "\tfloat4 " I_NORMALMATRICES"[32];\n" "\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n" "\tfloat4 " I_DEPTHPARAMS";\n" - "};\n");*/ + "\tfloat4 " I_STEREOPROJECTION"[8];\n" + "};\n"); ShaderCode code; char buf[16384]; @@ -79,7 +80,8 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy out.Write("void main()\n{\n"); out.Write("\tfor (int i = 0; i < gl_in.length(); ++i) {\n"); out.Write("\t\to = v[i];\n"); - out.Write("\t\tgl_Position = gl_in[i].gl_Position;\n"); + out.Write("\t\to.pos = float4(dot(" I_STEREOPROJECTION"[gl_InvocationID * 4 + 0], v[i].rawpos), dot(" I_STEREOPROJECTION"[gl_InvocationID * 4 + 1], v[i].rawpos), dot(" I_STEREOPROJECTION"[gl_InvocationID * 4 + 2], v[i].rawpos), dot(" I_STEREOPROJECTION"[gl_InvocationID * 4 + 3], v[i].rawpos)); \n"); + out.Write("\t\tgl_Position = o.pos;\n"); out.Write("\t\tgl_Layer = gl_InvocationID;\n"); out.Write("\t\tEmitVertex();\n"); out.Write("\t}\n"); diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 046384a923..bc98377049 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -264,6 +264,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T "\tfloat4 " I_NORMALMATRICES"[32];\n" "\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n" "\tfloat4 " I_DEPTHPARAMS";\n" + "\tfloat4 " I_STEREOPROJECTION"[8];\n" "};\n"); } diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index 54adb1ba17..b395b5e81f 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -239,3 +239,4 @@ private: #define I_NORMALMATRICES "cnmtx" #define I_POSTTRANSFORMMATRICES "cpostmtx" #define I_DEPTHPARAMS "cDepth" // farZ, zRange +#define I_STEREOPROJECTION "csproj" diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 2667445908..d7fd94ddec 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -52,6 +52,9 @@ static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type) if (g_ActiveConfig.bEnablePixelLighting) DefineVSOutputStructMember(object, api_type, "float4", "Normal", -1, "TEXCOORD", xfmem.numTexGen.numTexGens + 1); + if (g_ActiveConfig.bStereo) + DefineVSOutputStructMember(object, api_type, "float4", "rawpos", -1, "POSITION"); + object.Write("};\n"); } @@ -99,6 +102,7 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ "\tfloat4 " I_NORMALMATRICES"[32];\n" "\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n" "\tfloat4 " I_DEPTHPARAMS";\n" + "\tfloat4 " I_STEREOPROJECTION"[8];\n" "};\n"); GenerateVSOutputStruct(out, api_type); @@ -215,6 +219,9 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ out.Write("o.pos = float4(dot(" I_PROJECTION"[0], pos), dot(" I_PROJECTION"[1], pos), dot(" I_PROJECTION"[2], pos), dot(" I_PROJECTION"[3], pos));\n"); + if (g_ActiveConfig.bStereo) + out.Write("o.rawpos = pos;\n"); + out.Write("int4 lacc;\n" "float3 ldir, h;\n" "float dist, dist2, attn;\n"); diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index b62e2f93e3..e40eb92152 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -512,6 +512,30 @@ void VertexShaderManager::SetConstants() Matrix44::Multiply(s_viewportCorrection, projMtx, correctedMtx); memcpy(constants.projection, correctedMtx.data, 4*16); } + + if (g_ActiveConfig.bStereo && xfmem.projection.type == GX_PERSPECTIVE) + { + Matrix44 projMtx; + Matrix44::Set(projMtx, g_fProjectionMatrix); + + Matrix44 leftShearMtx, rightShearMtx; + Matrix44::Shear(leftShearMtx, g_ActiveConfig.iStereoSeparation / (200.0f * g_ActiveConfig.iStereoFocalLength)); + Matrix44::Shear(rightShearMtx, -g_ActiveConfig.iStereoSeparation / (200.0f * g_ActiveConfig.iStereoFocalLength)); + + Matrix44 leftProjMtx, rightProjMtx, leftCorrectedMtx, rightCorrectedMtx; + Matrix44::Multiply(projMtx, leftShearMtx, leftProjMtx); + Matrix44::Multiply(s_viewportCorrection, leftProjMtx, leftCorrectedMtx); + Matrix44::Multiply(projMtx, rightShearMtx, rightProjMtx); + Matrix44::Multiply(s_viewportCorrection, rightProjMtx, rightCorrectedMtx); + memcpy(constants.stereoprojection, leftCorrectedMtx.data, 4*16); + memcpy(constants.stereoprojection + 4, rightCorrectedMtx.data, 4*16); + } + else + { + memcpy(constants.stereoprojection, constants.projection, 4 * 16); + memcpy(constants.stereoprojection + 4, constants.projection, 4 * 16); + } + dirty = true; } } diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 5546fd2ce0..9962160486 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -67,8 +67,8 @@ void VideoConfig::Load(const std::string& ini_file) settings->Get("FreeLook", &bFreeLook, 0); settings->Get("UseFFV1", &bUseFFV1, 0); settings->Get("Stereo", &bStereo, false); - settings->Get("StereoSeparation", &iStereoSeparation, 200); - settings->Get("StereoFocalAngle", &iStereoFocalAngle, 0); + settings->Get("StereoSeparation", &iStereoSeparation, 65); + settings->Get("StereoFocalLength", &iStereoFocalLength, 100); settings->Get("EnablePixelLighting", &bEnablePixelLighting, 0); settings->Get("FastDepthCalc", &bFastDepthCalc, true); settings->Get("MSAA", &iMultisampleMode, 0); @@ -142,7 +142,7 @@ void VideoConfig::GameIniLoad() CHECK_SETTING("Video_Settings", "HiresTextures", bHiresTextures); CHECK_SETTING("Video_Settings", "Stereo", bStereo); CHECK_SETTING("Video_Settings", "StereoSeparation", iStereoSeparation); - CHECK_SETTING("Video_Settings", "StereoFocalAngle", iStereoFocalAngle); + CHECK_SETTING("Video_Settings", "StereoFocalLength", iStereoFocalLength); CHECK_SETTING("Video_Settings", "EnablePixelLighting", bEnablePixelLighting); CHECK_SETTING("Video_Settings", "FastDepthCalc", bFastDepthCalc); CHECK_SETTING("Video_Settings", "MSAA", iMultisampleMode); @@ -232,7 +232,7 @@ void VideoConfig::Save(const std::string& ini_file) settings->Set("UseFFV1", bUseFFV1); settings->Set("Stereo", bStereo); settings->Set("StereoSeparation", iStereoSeparation); - settings->Set("StereoFocalAngle", iStereoFocalAngle); + settings->Set("StereoFocalLength", iStereoFocalLength); settings->Set("EnablePixelLighting", bEnablePixelLighting); settings->Set("FastDepthCalc", bFastDepthCalc); settings->Set("ShowEFBCopyRegions", bShowEFBCopyRegions); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 11e4a47816..8f869dc100 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -94,7 +94,7 @@ struct VideoConfig final bool bFreeLook; bool bStereo; int iStereoSeparation; - int iStereoFocalAngle; + int iStereoFocalLength; bool bBorderlessFullscreen; // Hacks