mirror of
https://github.com/amwatson/CitraVR.git
synced 2024-09-20 03:11:40 +02:00
Super Immersive Mode
True 6DoF at last!
This commit is contained in:
parent
e97ca06b3d
commit
a20a05f118
18 changed files with 505 additions and 105 deletions
|
@ -387,7 +387,7 @@ public final class SettingsFragmentPresenter {
|
|||
sl.add(new CheckBoxSetting(SettingsFile.KEY_USE_DISK_SHADER_CACHE, Settings.SECTION_RENDERER, R.string.use_disk_shader_cache, R.string.use_disk_shader_cache_description, true, useDiskShaderCache));
|
||||
|
||||
sl.add(new HeaderSetting(null, null, R.string.stereoscopy, 0));
|
||||
sl.add(new SliderSetting(SettingsFile.KEY_FACTOR_3D, Settings.SECTION_RENDERER, R.string.factor3d, R.string.factor3d_description, 0, 200, "%", 50, factor3d));
|
||||
sl.add(new SliderSetting(SettingsFile.KEY_FACTOR_3D, Settings.SECTION_RENDERER, R.string.factor3d, R.string.factor3d_description, 0, 400, "%", 50, factor3d));
|
||||
|
||||
sl.add(new HeaderSetting(null, null, R.string.utility, 0));
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_DUMP_TEXTURES, Settings.SECTION_UTILITY, R.string.dump_textures, R.string.dump_textures_description, false, dumpTextures));
|
||||
|
@ -434,11 +434,15 @@ public final class SettingsFragmentPresenter {
|
|||
Setting vrCpuLevel = vrSection.getSetting(SettingsFile.KEY_VR_CPU_LEVEL);
|
||||
Setting vrImmersiveMode = vrSection.getSetting(SettingsFile.KEY_VR_IMMERSIVE_MODE);
|
||||
Setting vrImmersivePositionalFactor = vrSection.getSetting(SettingsFile.KEY_VR_IMMERSIVE_POSITIONAL_FACTOR);
|
||||
Setting vrImmersivePositionalGameScaler = vrSection.getSetting(SettingsFile.KEY_VR_IMMERSIVE_POSITIONAL_GAME_SCALER);
|
||||
Setting vrSIModeRegisterOffset = vrSection.getSetting(SettingsFile.KEY_VR_SI_MODE_REGISTER_OFFSET);
|
||||
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VR_ENVIRONMENT, Settings.SECTION_VR, R.string.vr_background, 0, R.array.vrBackgroundNames, R.array.vrBackgroundValues, VRUtils.getHMDType() == VRUtils.HMDType.QUEST3.getValue() ? 1 : 2, vrEnvironment));
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_VR_EXTRA_PERFORMANCE_MODE, Settings.SECTION_VR, R.string.vr_extra_performance_mode, R.string.vr_extra_performance_mode_description, false, vrExtraPerformanceMode));
|
||||
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VR_CPU_LEVEL, Settings.SECTION_VR, R.string.vr_cpu_level, R.string.vr_cpu_level_description, R.array.vrCpuLevelNames, R.array.vrCpuLevelValues, 3, vrCpuLevel));
|
||||
sl.add(new HeaderSetting(null, null, R.string.immersive_mode, 0));
|
||||
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VR_IMMERSIVE_MODE, Settings.SECTION_VR, R.string.vr_immersive_mode_title, R.string.vr_immersive_mode_description, R.array.vrImmersiveModeNames, R.array.vrImmersiveModeValues, 0, vrImmersiveMode));
|
||||
sl.add(new SliderSetting(SettingsFile.KEY_VR_SI_MODE_REGISTER_OFFSET, Settings.SECTION_VR, R.string.vr_si_mode_register_offset_title, R.string.vr_si_mode_register_offset_description, -1, 92, "", -1, vrSIModeRegisterOffset));
|
||||
sl.add(new SliderSetting(SettingsFile.KEY_VR_IMMERSIVE_POSITIONAL_FACTOR, Settings.SECTION_VR, R.string.vr_immersive_pos_factor_title, R.string.vr_immersive_pos_factor_description, 0, 40, "X", 0, vrImmersivePositionalFactor));
|
||||
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VR_IMMERSIVE_POSITIONAL_GAME_SCALER, Settings.SECTION_VR, R.string.vr_immersive_pos_game_scaler_title, R.string.vr_immersive_pos_game_scaler_description, R.array.vrPosFactorGameScalerNames, R.array.vrPosFactorGameScalerValues, 0, vrImmersivePositionalGameScaler));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,9 @@ public final class SettingsFile {
|
|||
|
||||
public static final String KEY_VR_IMMERSIVE_POSITIONAL_FACTOR = "vr_immersive_positional_factor";
|
||||
|
||||
public static final String KEY_VR_IMMERSIVE_POSITIONAL_GAME_SCALER = "vr_immersive_positional_game_scaler";
|
||||
public static final String KEY_VR_SI_MODE_REGISTER_OFFSET = "vr_si_mode_register_offset";
|
||||
|
||||
public static final String KEY_LOG_FILTER = "log_filter";
|
||||
|
||||
private static BiMap<String, String> sectionsMap = new BiMap<>();
|
||||
|
|
|
@ -308,9 +308,15 @@ void Config::ReadValues() {
|
|||
VRSettings::values.vr_immersive_mode = sdl2_config->GetInteger(
|
||||
"VR", "vr_immersive_mode", 0);
|
||||
Settings::values.vr_immersive_mode = VRSettings::values.vr_immersive_mode;
|
||||
VRSettings::values.vr_si_mode_register_offset = sdl2_config->GetInteger(
|
||||
"VR", "vr_si_mode_register_offset", 0);
|
||||
Settings::values.vr_si_mode_register_offset = VRSettings::values.vr_si_mode_register_offset;
|
||||
VRSettings::values.vr_immersive_positional_factor = sdl2_config->GetInteger(
|
||||
"VR", "vr_immersive_positional_factor", 0);
|
||||
Settings::values.vr_immersive_positional_factor = VRSettings::values.vr_immersive_positional_factor;
|
||||
VRSettings::values.vr_immersive_positional_game_scaler = sdl2_config->GetInteger(
|
||||
"VR", "vr_immersive_positional_game_scaler", 0);
|
||||
Settings::values.vr_immersive_positional_game_scaler = VRSettings::values.vr_immersive_positional_game_scaler;
|
||||
|
||||
if (Settings::values.vr_immersive_mode.GetValue() > 0) {
|
||||
LOG_INFO(Config, "VR immersive mode enabled");
|
||||
|
|
|
@ -31,8 +31,7 @@ License : Licensed under GPLv3 or any later version.
|
|||
namespace {
|
||||
|
||||
constexpr float defaultLowerPanelScaleFactor = 0.75f;
|
||||
|
||||
const std::vector<float> immersiveLevelFactor = {1.0f, 5.0f, 3.0f};
|
||||
constexpr float superImmersiveRadius = 0.5f;
|
||||
|
||||
/** Used to translate texture coordinates into the corresponding coordinates
|
||||
* on the Android Activity Window.
|
||||
|
@ -254,20 +253,55 @@ void GameSurfaceLayer::SetSurface() const {
|
|||
}
|
||||
|
||||
void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLayer>& layers,
|
||||
uint32_t& layerCount, const bool showLowerPanel) const
|
||||
uint32_t& layerCount, const XrPosef& headPose, const float& immersiveModeFactor, const bool showLowerPanel)
|
||||
|
||||
{
|
||||
const uint32_t panelWidth = swapchain_.Width / 2;
|
||||
const uint32_t panelHeight = swapchain_.Height / 2;
|
||||
const double aspectRatio =
|
||||
static_cast<double>(2 * panelWidth) / static_cast<double>(panelHeight);
|
||||
|
||||
/*
|
||||
* This bit is entirely optional, rather than having the panel appear/disappear it emerge in
|
||||
* smoothly, however to achieve it I had to make the scale factor mutable, which I appreciate
|
||||
* might not be following the intention of this class.
|
||||
* If a mutable class member isn't desired, then just drop this bit and use the visibleLowerPanel
|
||||
* variable directly.
|
||||
*/
|
||||
const auto panelZoomSpeed = 0.15f;
|
||||
if (showLowerPanel && lowerPanelScaleFactor < defaultLowerPanelScaleFactor)
|
||||
{
|
||||
if (lowerPanelScaleFactor == 0.0f)
|
||||
{
|
||||
lowerPanelScaleFactor = panelZoomSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
lowerPanelScaleFactor *= 1.0f + panelZoomSpeed;
|
||||
lowerPanelScaleFactor = std::min(lowerPanelScaleFactor, defaultLowerPanelScaleFactor);
|
||||
}
|
||||
}
|
||||
else if (!showLowerPanel && lowerPanelScaleFactor > 0.0f)
|
||||
{
|
||||
lowerPanelScaleFactor /= 1.0f + panelZoomSpeed;
|
||||
if (lowerPanelScaleFactor < panelZoomSpeed)
|
||||
{
|
||||
lowerPanelScaleFactor = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent a seam between the top and bottom view
|
||||
constexpr uint32_t verticalBorderTex = 1;
|
||||
const bool useCylinder = (GetCylinderSysprop() != 0) || (immersiveMode_ > 0);
|
||||
if (useCylinder) {
|
||||
|
||||
// Create the Top Display Panel (Curved display)
|
||||
for (uint32_t eye = 0; eye < NUM_EYES; eye++) {
|
||||
XrPosef topPanelFromWorld = topPanelFromWorld_;
|
||||
if (immersiveMode_ >= 3 && !showLowerPanel)
|
||||
{
|
||||
topPanelFromWorld = GetTopPanelFromHeadPose(eye, headPose);
|
||||
}
|
||||
|
||||
XrCompositionLayerCylinderKHR layer = {};
|
||||
|
||||
layer.type = XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR;
|
||||
|
@ -278,6 +312,12 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
|
|||
|
||||
layer.space = space;
|
||||
|
||||
// Radius effectively controls the width of the cylinder shape.
|
||||
// Central angle controls how much of the cylinder is
|
||||
// covered by the texture. Together, they control the
|
||||
// scale of the texture.
|
||||
const float radius = (immersiveMode_ <= 2 || showLowerPanel) ? GetRadiusSysprop() : superImmersiveRadius;
|
||||
|
||||
layer.eyeVisibility = eye == 0 ? XR_EYE_VISIBILITY_LEFT : XR_EYE_VISIBILITY_RIGHT;
|
||||
memset(&layer.subImage, 0, sizeof(XrSwapchainSubImage));
|
||||
layer.subImage.swapchain = swapchain_.Handle;
|
||||
|
@ -286,17 +326,11 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
|
|||
layer.subImage.imageRect.extent.width = panelWidth;
|
||||
layer.subImage.imageRect.extent.height = panelHeight - verticalBorderTex;
|
||||
layer.subImage.imageArrayIndex = 0;
|
||||
layer.pose = topPanelFromWorld_;
|
||||
layer.pose.position.z += GetRadiusSysprop();
|
||||
|
||||
// Radius effectively controls the width of the cylinder shape.
|
||||
// Central angle controls how much of the cylinder is
|
||||
// covered by the texture. Together, they control the
|
||||
// scale of the texture.
|
||||
const float radius = GetRadiusSysprop();
|
||||
layer.pose = topPanelFromWorld;
|
||||
layer.pose.position.z += (immersiveMode_ < 3) ? radius : 0.0f;
|
||||
layer.radius = radius;
|
||||
layer.centralAngle = (!immersiveMode_ ? GetCentralAngleSysprop()
|
||||
: 55.0f * immersiveLevelFactor[immersiveMode_]) *
|
||||
: GameSurfaceLayer::DEFAULT_CYLINDER_CENTRAL_ANGLE_DEGREES * immersiveModeFactor) *
|
||||
MATH_FLOAT_PI / 180.0f;
|
||||
layer.aspectRatio = -aspectRatio;
|
||||
layers[layerCount++].mCylinder = layer;
|
||||
|
@ -335,35 +369,6 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This bit is entirely optional, rather than having the panel appear/disappear it emerge in
|
||||
* smoothly, however to achieve it I had to make the scale factor mutable, which I appreciate
|
||||
* might not be following the intention of this class.
|
||||
* If a mutable class member isn't desired, then just drop this bit and use the visibleLowerPanel
|
||||
* variable directly.
|
||||
*/
|
||||
const auto panelZoomSpeed = 0.15f;
|
||||
if (showLowerPanel && lowerPanelScaleFactor < defaultLowerPanelScaleFactor)
|
||||
{
|
||||
if (lowerPanelScaleFactor == 0.0f)
|
||||
{
|
||||
lowerPanelScaleFactor = panelZoomSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
lowerPanelScaleFactor *= 1.0f + panelZoomSpeed;
|
||||
lowerPanelScaleFactor = std::min(lowerPanelScaleFactor, defaultLowerPanelScaleFactor);
|
||||
}
|
||||
}
|
||||
else if (!showLowerPanel && lowerPanelScaleFactor > 0.0f)
|
||||
{
|
||||
lowerPanelScaleFactor /= 1.0f + panelZoomSpeed;
|
||||
if (lowerPanelScaleFactor < panelZoomSpeed)
|
||||
{
|
||||
lowerPanelScaleFactor = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create the Lower Display Panel (flat touchscreen)
|
||||
// When citra is in stereo mode, this panel is also rendered in stereo (i.e.
|
||||
|
@ -389,14 +394,14 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
|
|||
memset(&layer.subImage, 0, sizeof(XrSwapchainSubImage));
|
||||
layer.subImage.swapchain = swapchain_.Handle;
|
||||
layer.subImage.imageRect.offset.x =
|
||||
(cropHoriz / 2) / immersiveLevelFactor[immersiveMode_] +
|
||||
panelWidth * (0.5f - (0.5f / immersiveLevelFactor[immersiveMode_]));
|
||||
(cropHoriz / 2) / immersiveModeFactor +
|
||||
panelWidth * (0.5f - (0.5f / immersiveModeFactor));
|
||||
layer.subImage.imageRect.offset.y =
|
||||
panelHeight + verticalBorderTex +
|
||||
panelHeight * (0.5f - (0.5f / immersiveLevelFactor[immersiveMode_]));
|
||||
panelHeight * (0.5f - (0.5f / immersiveModeFactor));
|
||||
layer.subImage.imageRect.extent.width =
|
||||
(panelWidth - cropHoriz) / immersiveLevelFactor[immersiveMode_];
|
||||
layer.subImage.imageRect.extent.height = panelHeight / immersiveLevelFactor[immersiveMode_];
|
||||
(panelWidth - cropHoriz) / immersiveModeFactor;
|
||||
layer.subImage.imageRect.extent.height = panelHeight / immersiveModeFactor;
|
||||
layer.subImage.imageArrayIndex = 0;
|
||||
layer.pose = lowerPanelFromWorld_;
|
||||
const auto scale = GetDensityScaleForSize(panelWidth - cropHoriz, -panelHeight,
|
||||
|
@ -453,6 +458,23 @@ void GameSurfaceLayer::SetTopPanelFromController(const XrVector3f& controllerPos
|
|||
topPanelFromWorld_ = XrPosef{windowRotation, windowPosition};
|
||||
}
|
||||
|
||||
XrPosef GameSurfaceLayer::GetTopPanelFromHeadPose(uint32_t eye, const XrPosef& headPose) {
|
||||
XrVector3f panelPosition = headPose.position;
|
||||
|
||||
XrVector3f forward, up, right;
|
||||
XrMath::Quatf::ToVectors(headPose.orientation, forward, right, up);
|
||||
|
||||
panelPosition.z += superImmersiveRadius * (forward.x * 0.4f);
|
||||
panelPosition.y -= superImmersiveRadius * (forward.z * 0.4f);
|
||||
panelPosition.x += superImmersiveRadius * (forward.y * 0.4f);
|
||||
|
||||
panelPosition.z += up.x / 12.f;
|
||||
panelPosition.y -= up.z / 12.f;
|
||||
panelPosition.x += up.y / 12.f;
|
||||
|
||||
return XrPosef{headPose.orientation, panelPosition};
|
||||
}
|
||||
|
||||
// based on thumbstick, modify the depth of the top panel
|
||||
void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
|
||||
static constexpr float kDepthSpeed = 0.05f;
|
||||
|
|
|
@ -101,7 +101,8 @@ public:
|
|||
* @param visibleLowerPanel whether the lower panel is shown/visible
|
||||
*/
|
||||
void Frame(const XrSpace& space, std::vector<XrCompositionLayer>& layers,
|
||||
uint32_t& layerCount, const bool visibleLowerPanel) const;
|
||||
uint32_t& layerCount, const XrPosef& headPose,
|
||||
const float& immersiveModeFactor, const bool visibleLowerPanel);
|
||||
|
||||
/** Given an origin, direction of a ray,
|
||||
* returns the coordinates of where the ray will intersects
|
||||
|
@ -127,6 +128,7 @@ public:
|
|||
bool GetRayIntersectionWithPanelTopPanel(const XrVector3f& start, const XrVector3f& end,
|
||||
XrVector2f& result2d, XrPosef& result3d) const;
|
||||
void SetTopPanelFromController(const XrVector3f& controllerPosition);
|
||||
XrPosef GetTopPanelFromHeadPose(uint32_t eye, const XrPosef& headPose);
|
||||
|
||||
void SetTopPanelFromThumbstick(const float thumbstickY);
|
||||
|
||||
|
|
|
@ -88,6 +88,112 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class Matrixf
|
||||
{
|
||||
public:
|
||||
static void Identity(XrVector4f mat[4]) {
|
||||
mat[0] = {1.f, 0.f, 0.f, 0.f};
|
||||
mat[1] = {0.f, 1.f, 0.f, 0.f};
|
||||
mat[2] = {0.f, 0.f, 1.f, 0.f};
|
||||
mat[3] = {0.f, 0.f, 0.f, 1.f};
|
||||
}
|
||||
|
||||
static XrVector4f XrVector4f_Multiply(const XrVector4f mat[4], const XrVector4f &v)
|
||||
{
|
||||
XrVector4f out;
|
||||
out.x = mat[0].x * v.x + mat[0].y * v.y + mat[0].z * v.z + mat[0].w * v.w;
|
||||
out.y = mat[1].x * v.x + mat[1].y * v.y + mat[1].z * v.z + mat[1].w * v.w;
|
||||
out.z = mat[2].x * v.x + mat[2].y * v.y + mat[2].z * v.z + mat[2].w * v.w;
|
||||
out.w = mat[3].x * v.x + mat[3].y * v.y + mat[3].z * v.z + mat[3].w * v.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
static XrVector3f XrVector3f_Multiply(const XrVector3f mat[3], const XrVector3f &v)
|
||||
{
|
||||
XrVector3f out;
|
||||
out.x = mat[0].x * v.x + mat[0].y * v.y + mat[0].z * v.z;
|
||||
out.y = mat[1].x * v.x + mat[1].y * v.y + mat[1].z * v.z;
|
||||
out.z = mat[2].x * v.x + mat[2].y * v.y + mat[2].z * v.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Returns a 3x3 minor of a 4x4 matrix.
|
||||
static float ToMinor(const float *matrix, int r0, int r1, int r2, int c0, int c1, int c2) {
|
||||
return matrix[4 * r0 + c0] *
|
||||
(matrix[4 * r1 + c1] * matrix[4 * r2 + c2] - matrix[4 * r2 + c1] * matrix[4 * r1 + c2]) -
|
||||
matrix[4 * r0 + c1] *
|
||||
(matrix[4 * r1 + c0] * matrix[4 * r2 + c2] - matrix[4 * r2 + c0] * matrix[4 * r1 + c2]) +
|
||||
matrix[4 * r0 + c2] *
|
||||
(matrix[4 * r1 + c0] * matrix[4 * r2 + c1] - matrix[4 * r2 + c0] * matrix[4 * r1 + c1]);
|
||||
}
|
||||
|
||||
static void ToInverse(const XrVector4f in[4], XrVector4f out[4]) {
|
||||
float *matrix = (float*)in;
|
||||
float *inv_mat = (float*)out;
|
||||
const float rcpDet =
|
||||
1.0f / (matrix[0] * ToMinor(matrix, 1, 2, 3, 1, 2, 3) -
|
||||
matrix[1] * ToMinor(matrix, 1, 2, 3, 0, 2, 3) +
|
||||
matrix[2] * ToMinor(matrix, 1, 2, 3, 0, 1, 3) -
|
||||
matrix[3] * ToMinor(matrix, 1, 2, 3, 0, 1, 2));
|
||||
|
||||
inv_mat[0] = ToMinor(matrix, 1, 2, 3, 1, 2, 3) * rcpDet;
|
||||
inv_mat[1] = -ToMinor(matrix, 0, 2, 3, 1, 2, 3) * rcpDet;
|
||||
inv_mat[2] = ToMinor(matrix, 0, 1, 3, 1, 2, 3) * rcpDet;
|
||||
inv_mat[3] = -ToMinor(matrix, 0, 1, 2, 1, 2, 3) * rcpDet;
|
||||
inv_mat[4] = -ToMinor(matrix, 1, 2, 3, 0, 2, 3) * rcpDet;
|
||||
inv_mat[5] = ToMinor(matrix, 0, 2, 3, 0, 2, 3) * rcpDet;
|
||||
inv_mat[6] = -ToMinor(matrix, 0, 1, 3, 0, 2, 3) * rcpDet;
|
||||
inv_mat[7] = ToMinor(matrix, 0, 1, 2, 0, 2, 3) * rcpDet;
|
||||
inv_mat[8] = ToMinor(matrix, 1, 2, 3, 0, 1, 3) * rcpDet;
|
||||
inv_mat[9] = -ToMinor(matrix, 0, 2, 3, 0, 1, 3) * rcpDet;
|
||||
inv_mat[10] = ToMinor(matrix, 0, 1, 3, 0, 1, 3) * rcpDet;
|
||||
inv_mat[11] = -ToMinor(matrix, 0, 1, 2, 0, 1, 3) * rcpDet;
|
||||
inv_mat[12] = -ToMinor(matrix, 1, 2, 3, 0, 1, 2) * rcpDet;
|
||||
inv_mat[13] = ToMinor(matrix, 0, 2, 3, 0, 1, 2) * rcpDet;
|
||||
inv_mat[14] = -ToMinor(matrix, 0, 1, 3, 0, 1, 2) * rcpDet;
|
||||
inv_mat[15] = ToMinor(matrix, 0, 1, 2, 0, 1, 2) * rcpDet;
|
||||
}
|
||||
|
||||
static void Projection(XrVector4f result[4], const float fov_x, const float fov_y,
|
||||
const float nearZ, const float farZ) {
|
||||
float *projectionMatrix = (float*)result;
|
||||
|
||||
float xmin, xmax, ymin, ymax;
|
||||
float width, height, depth;
|
||||
|
||||
|
||||
ymax = nearZ * tan( fov_y );
|
||||
ymin = -ymax;
|
||||
|
||||
xmax = nearZ * tan( fov_x );
|
||||
xmin = -xmax;
|
||||
|
||||
width = xmax - xmin;
|
||||
height = ymax - ymin;
|
||||
depth = farZ - nearZ;
|
||||
|
||||
projectionMatrix[0] = 2 * nearZ / width;
|
||||
projectionMatrix[4] = 0;
|
||||
projectionMatrix[8] = ( xmax + xmin ) / width;
|
||||
projectionMatrix[12] = 0;
|
||||
|
||||
projectionMatrix[1] = 0;
|
||||
projectionMatrix[5] = 2 * nearZ / height;
|
||||
projectionMatrix[9] = ( ymax + ymin ) / height;
|
||||
projectionMatrix[13] = 0;
|
||||
|
||||
projectionMatrix[2] = 0;
|
||||
projectionMatrix[6] = 0;
|
||||
projectionMatrix[10] = -( farZ + nearZ ) / depth;
|
||||
projectionMatrix[14] = -2 * farZ * nearZ / depth;
|
||||
|
||||
projectionMatrix[3] = 0;
|
||||
projectionMatrix[7] = 0;
|
||||
projectionMatrix[11] = -1;
|
||||
projectionMatrix[15] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class Quatf {
|
||||
public:
|
||||
static XrQuaternionf Identity() {
|
||||
|
@ -187,6 +293,65 @@ public:
|
|||
(up.z - forward.y) / s};
|
||||
}
|
||||
}
|
||||
|
||||
static void ToRotationMatrix(const XrQuaternionf& q, float rotation[16]) {
|
||||
|
||||
float x2 = q.x + q.x;
|
||||
float y2 = q.y + q.y;
|
||||
float z2 = q.z + q.z;
|
||||
float xx2 = q.x * x2;
|
||||
float xy2 = q.x * y2;
|
||||
float xz2 = q.x * z2;
|
||||
float yy2 = q.y * y2;
|
||||
float yz2 = q.y * z2;
|
||||
float zz2 = q.z * z2;
|
||||
float sx2 = q.w * x2;
|
||||
float sy2 = q.w * y2;
|
||||
float sz2 = q.w * z2;
|
||||
|
||||
float r[16] = {1 - (yy2 + zz2), xy2 + sz2, xz2 - sy2, 0.f, // column 0
|
||||
xy2 - sz2, 1 - (xx2 + zz2), yz2 + sx2, 0.f, // column 1
|
||||
xz2 + sy2, yz2 - sx2, 1 - (xx2 + yy2), 0.f, // column 2
|
||||
0.f, 0.f, 0.f, 1};// column 3
|
||||
|
||||
std::memcpy(rotation, r, sizeof(float ) * 16);
|
||||
}
|
||||
|
||||
static void ToVectors(const XrQuaternionf& q, XrVector3f& forward,
|
||||
XrVector3f& right, XrVector3f& up) {
|
||||
XrVector3f mat[3];
|
||||
const float ww = q.w * q.w;
|
||||
const float xx = q.x * q.x;
|
||||
const float yy = q.y * q.y;
|
||||
const float zz = q.z * q.z;
|
||||
|
||||
mat[0] = {
|
||||
ww + xx - yy - zz,
|
||||
2 * (q.x * q.y - q.w * q.z),
|
||||
2 * (q.x * q.z + q.w * q.y)};
|
||||
|
||||
mat[1] = {
|
||||
2 * (q.x * q.y + q.w * q.z),
|
||||
ww - xx + yy - zz,
|
||||
2 * (q.y * q.z - q.w * q.x)};
|
||||
|
||||
mat[2] = {
|
||||
2 * (q.x * q.z - q.w * q.y),
|
||||
2 * (q.y * q.z + q.w * q.x),
|
||||
ww - xx - yy + zz};
|
||||
|
||||
XrVector3f glFlip[3] = {{0, 0, -1},
|
||||
{1, 0, 0},
|
||||
{0, 1, 0}};
|
||||
|
||||
XrVector3f f = Matrixf::XrVector3f_Multiply(mat, glFlip[0]);
|
||||
XrVector3f r = Matrixf::XrVector3f_Multiply(mat, glFlip[1]);
|
||||
XrVector3f u = Matrixf::XrVector3f_Multiply(mat, glFlip[2]);
|
||||
|
||||
forward = {-f.z, -f.x, f.y};
|
||||
right = {-r.z, -r.x, r.y};
|
||||
up = {-u.z, -u.x, u.y};
|
||||
}
|
||||
};
|
||||
|
||||
class Posef {
|
||||
|
|
|
@ -77,6 +77,8 @@ std::chrono::time_point<std::chrono::steady_clock> gOnCreateStartTime;
|
|||
std::atomic<bool> gShouldShowErrorMessage = {false};
|
||||
std::unique_ptr<OpenXr> gOpenXr;
|
||||
|
||||
const std::vector<float> immersiveScaleFactor = {1.0f, 5.0f, 3.0f, 1.8f};
|
||||
|
||||
void ForwardButtonStateChangeToCitra(JNIEnv* jni, jobject activityObject,
|
||||
jmethodID forwardVRInputMethodID, const int androidButtonCode,
|
||||
const XrBool32 xrButtonState) {
|
||||
|
@ -487,40 +489,90 @@ private:
|
|||
gOpenXr->headLocation = {XR_TYPE_SPACE_LOCATION};
|
||||
OXR(xrLocateSpace(gOpenXr->viewSpace_, gOpenXr->headSpace_, frameState.predictedDisplayTime, &gOpenXr->headLocation));
|
||||
|
||||
bool showLowerPanel = true;
|
||||
// Push the HMD position through to the Rasterizer to pass on to the VS Uniform
|
||||
if (VideoCore::g_renderer && VideoCore::g_renderer->Rasterizer())
|
||||
mInputStateFrame.SyncHandPoses(gOpenXr->session_, mInputStateStatic, gOpenXr->localSpace_,
|
||||
frameState.predictedDisplayTime);
|
||||
|
||||
//XrMath::Vector3f::
|
||||
XrVector3f leftVec = {
|
||||
gOpenXr->headLocation.pose.position.x - mInputStateFrame.mHandPositions[InputStateFrame::LEFT_CONTROLLER].pose.position.x,
|
||||
gOpenXr->headLocation.pose.position.y - mInputStateFrame.mHandPositions[InputStateFrame::LEFT_CONTROLLER].pose.position.y,
|
||||
gOpenXr->headLocation.pose.position.z - mInputStateFrame.mHandPositions[InputStateFrame::LEFT_CONTROLLER].pose.position.z,
|
||||
};
|
||||
const float lengthLeft = XrMath::Vector3f::Length(leftVec);
|
||||
XrVector3f rightVec = {
|
||||
gOpenXr->headLocation.pose.position.x - mInputStateFrame.mHandPositions[InputStateFrame::RIGHT_CONTROLLER].pose.position.x,
|
||||
gOpenXr->headLocation.pose.position.y - mInputStateFrame.mHandPositions[InputStateFrame::RIGHT_CONTROLLER].pose.position.y,
|
||||
gOpenXr->headLocation.pose.position.z - mInputStateFrame.mHandPositions[InputStateFrame::RIGHT_CONTROLLER].pose.position.z,
|
||||
};
|
||||
const float lengthRight = XrMath::Vector3f::Length(rightVec);
|
||||
const float length = std::min(lengthLeft, lengthRight);
|
||||
|
||||
// This block is for testing which uinform offset is needed
|
||||
// for a given game to implement new super-immersive profiles if needed
|
||||
static bool increase = false;
|
||||
static int uoffset = -1;
|
||||
{
|
||||
//I am confused... but GetRollInRadians appears to return pitch
|
||||
float pitch = XrMath::Quatf::GetRollInRadians(gOpenXr->headLocation.pose.orientation);
|
||||
|
||||
if ((VRSettings::values.vr_immersive_positional_factor == 0) ||
|
||||
(pitch < -0.35f))
|
||||
if (VRSettings::values.vr_immersive_mode > 90)
|
||||
{
|
||||
//Disable position when looking down at the lower panel
|
||||
Common::Vec3f position = {};
|
||||
VideoCore::g_renderer->Rasterizer()->SetVRData(position);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Only use position if it is enabled, and the user is not looking at the lower panel
|
||||
Common::Vec3f position{-gOpenXr->headLocation.pose.position.y,
|
||||
gOpenXr->headLocation.pose.position.x,
|
||||
-gOpenXr->headLocation.pose.position.z};// - For some reason Z doesn't affect the actual Z position!
|
||||
if (mInputStateFrame.mThumbrestTouchState[InputStateFrame::RIGHT_CONTROLLER].currentState)
|
||||
{
|
||||
if (increase)
|
||||
{
|
||||
++uoffset;
|
||||
increase = false;
|
||||
}
|
||||
|
||||
ALOGI("gOpenXr->headLocation Position : {}.{}.{}",
|
||||
position.x,
|
||||
position.y,
|
||||
position.z);
|
||||
|
||||
position *= VRSettings::values.vr_immersive_positional_factor;
|
||||
VideoCore::g_renderer->Rasterizer()->SetVRData(position);
|
||||
showLowerPanel = false;
|
||||
//There are 96 Vec4f; since we are applying 4 of them at a time we need to loop
|
||||
// after 92
|
||||
if (uoffset > 92)
|
||||
{
|
||||
uoffset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
increase = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mInputStateFrame.SyncHandPoses(gOpenXr->session_, mInputStateStatic, gOpenXr->localSpace_,
|
||||
frameState.predictedDisplayTime);
|
||||
bool showLowerPanel = true;
|
||||
float immersiveModeFactor = (VRSettings::values.vr_immersive_mode <= 2) ? immersiveScaleFactor[VRSettings::values.vr_immersive_mode] : immersiveScaleFactor[3];
|
||||
// Push the HMD position through to the Rasterizer to pass on to the VS Uniform
|
||||
if (VideoCore::g_renderer && VideoCore::g_renderer->Rasterizer())
|
||||
{
|
||||
if ((VRSettings::values.vr_immersive_positional_factor == 0) ||
|
||||
//If in Normal immersive modes then look down for the lower panel to reveal itself (for some reason the Roll function returns pitch)
|
||||
(VRSettings::values.vr_immersive_mode <= 2 && XrMath::Quatf::GetRollInRadians(gOpenXr->headLocation.pose.orientation) < -MATH_FLOAT_PI / 8.0f) ||
|
||||
//If in "super immersive" mode then put controller next to head in order to disable the mode temporarily
|
||||
(VRSettings::values.vr_immersive_mode >= 3 && length < 0.2))
|
||||
{
|
||||
XrVector4f identity[4] = {};
|
||||
XrMath::Matrixf::Identity(identity);
|
||||
immersiveModeFactor = 1.0f;
|
||||
VideoCore::g_renderer->Rasterizer()->SetVRData(1, immersiveModeFactor, -1, (float*)identity);
|
||||
}
|
||||
else
|
||||
{
|
||||
XrVector4f transform[4] = {};
|
||||
XrMath::Quatf::ToRotationMatrix(gOpenXr->headLocation.pose.orientation, (float*)transform);
|
||||
|
||||
//Calculate the inverse
|
||||
XrVector4f inv_transform[4];
|
||||
XrMath::Matrixf::ToInverse(transform, inv_transform);
|
||||
|
||||
XrQuaternionf invertedOrientation = XrMath::Quatf::Inverted(gOpenXr->headLocation.pose.orientation);
|
||||
XrVector3f position = XrMath::Quatf::Rotate(invertedOrientation, gOpenXr->headLocation.pose.position);
|
||||
|
||||
float posScaler = powf(10.f, VRSettings::values.vr_immersive_positional_game_scaler);
|
||||
inv_transform[3].x = -position.x * VRSettings::values.vr_immersive_positional_factor * posScaler;
|
||||
inv_transform[3].y = -position.y * VRSettings::values.vr_immersive_positional_factor * posScaler;
|
||||
inv_transform[3].z = -position.z * VRSettings::values.vr_immersive_positional_factor * posScaler;
|
||||
|
||||
VideoCore::g_renderer->Rasterizer()->SetVRData(VRSettings::values.vr_immersive_mode, immersiveModeFactor, uoffset, (float*)inv_transform);
|
||||
showLowerPanel = false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Set the compositor layers for this frame.
|
||||
|
@ -537,7 +589,8 @@ private:
|
|||
layers[layerCount++].Passthrough = passthroughLayer;
|
||||
}
|
||||
|
||||
mGameSurfaceLayer->Frame(gOpenXr->localSpace_, layers, layerCount, showLowerPanel);
|
||||
mGameSurfaceLayer->Frame(gOpenXr->localSpace_, layers, layerCount, gOpenXr->headLocation.pose,
|
||||
immersiveModeFactor, showLowerPanel);
|
||||
#if defined(UI_LAYER)
|
||||
if (gShouldShowErrorMessage) {
|
||||
XrCompositionLayerQuad quadLayer = {};
|
||||
|
|
|
@ -42,7 +42,9 @@ struct Values {
|
|||
uint32_t resolution_factor = 0;
|
||||
int32_t vr_environment = 0;
|
||||
int32_t vr_immersive_mode = 0;
|
||||
int32_t vr_si_mode_register_offset = -1;
|
||||
int32_t vr_immersive_positional_factor = 0;
|
||||
int32_t vr_immersive_positional_game_scaler = 0;
|
||||
bool extra_performance_mode_enabled = false;
|
||||
} extern values;
|
||||
|
||||
|
|
|
@ -229,11 +229,27 @@
|
|||
<item>Off</item>
|
||||
<item>Large - Low Resolution</item>
|
||||
<item>Higher Resolution</item>
|
||||
<item>Super Immersive - Profile 1</item>
|
||||
<item>Super Immersive - Profile 2 (Set Register Offset for game)</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="vrImmersiveModeValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="vrPosFactorGameScalerNames">
|
||||
<item>1x</item>
|
||||
<item>10x</item>
|
||||
<item>100x</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="vrPosFactorGameScalerValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
</resources>
|
||||
|
|
|
@ -303,8 +303,12 @@
|
|||
<string name="immersive_mode">Immersive Mode</string>
|
||||
<string name="vr_immersive_mode_title">[WARNING: Graphics Artifacts] Immersive Mode (Experimental)</string>
|
||||
<string name="vr_immersive_mode_description">Extends the top screen around a cylinder for immersive gameplay</string>
|
||||
<string name="vr_si_mode_register_offset_title">Super Immersive Mode Profile 2 Register Offset</string>
|
||||
<string name="vr_si_mode_register_offset_description">Sets the register offset used for the view when using Super Immersive Mode Profile 2 - varies by game</string>
|
||||
<string name="vr_immersive_pos_factor_title">Immersive Mode Positional Movement Factor</string>
|
||||
<string name="vr_immersive_pos_factor_description">Adjusts how much movement left/right/up/down affects the game camera (0 = disabled)</string>
|
||||
<string name="vr_immersive_pos_game_scaler_title">Adjusts Positional Movement Factor by a scaler</string>
|
||||
<string name="vr_immersive_pos_game_scaler_description">Adjusts how much movement left/right/up/down affects the game camera, some games required larger values, so this multiplies the positional factor</string>
|
||||
<string name="vr_graphics_warning">DANGER: not all games/levels look good in immersive mode. Large visual artifacts are common when this option is selected</string>
|
||||
<string name="vr_graphics_warning_short">WARNING: this WILL cause visual artifacting in most content</string>
|
||||
</resources>
|
||||
|
|
|
@ -528,7 +528,9 @@ struct Values {
|
|||
|
||||
// VR
|
||||
Setting<u32> vr_immersive_mode{0, "vr_immersive_mode"};
|
||||
Setting<u32> vr_si_mode_register_offset{-1, "vr_si_mode_register_offset"};
|
||||
Setting<u32> vr_immersive_positional_factor{0, "vr_immersive_positional_factor"};
|
||||
Setting<u32> vr_immersive_positional_game_scaler{0, "vr_immersive_positional_game_scaler"};
|
||||
};
|
||||
|
||||
extern Values values;
|
||||
|
|
|
@ -13,8 +13,6 @@ namespace VideoCore {
|
|||
|
||||
using Pica::f24;
|
||||
|
||||
const std::vector<float> immersiveLevelFactor = {1.0f, 5.0f, 3.0f};
|
||||
|
||||
static Common::Vec4f ColorRGBA8(const u32 color) {
|
||||
const auto rgba =
|
||||
Common::Vec4u{color >> 0 & 0xFF, color >> 8 & 0xFF, color >> 16 & 0xFF, color >> 24 & 0xFF};
|
||||
|
@ -139,7 +137,6 @@ void RasterizerAccelerated::SyncEntireState() {
|
|||
|
||||
// Sync uniforms
|
||||
SyncClipPlane();
|
||||
SyncVRData();
|
||||
SyncDepthScale();
|
||||
SyncDepthOffset();
|
||||
SyncAlphaTest();
|
||||
|
@ -864,19 +861,105 @@ void RasterizerAccelerated::SyncClipPlane() {
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerAccelerated::SyncVRData() {
|
||||
if (vs_uniform_block_data.data.vr_immersive_mode_factor != immersiveLevelFactor[Settings::values.vr_immersive_mode.GetValue()])
|
||||
void RasterizerAccelerated::SetVRData(const int32_t &vrImmersiveMode, const float& immersiveModeFactor, int uoffset, const float view[16])
|
||||
{
|
||||
if (vs_uniform_block_data.data.vr_immersive_mode_factor != immersiveModeFactor)
|
||||
{
|
||||
vs_uniform_block_data.data.vr_immersive_mode_factor = immersiveLevelFactor[Settings::values.vr_immersive_mode.GetValue()];
|
||||
vs_uniform_block_data.data.vr_immersive_mode_factor = immersiveModeFactor;
|
||||
vs_uniform_block_data.dirty = true;
|
||||
}
|
||||
|
||||
vr_uoffset = uoffset;
|
||||
vr_immersive_mode = vrImmersiveMode;
|
||||
std::memcpy(vr_view, view, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
static void MatrixTranspose(float m[16], const float src[16]) {
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
m[i * 4 + j] = src[j * 4 + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerAccelerated::SetVRData(Common::Vec3f position)
|
||||
{
|
||||
//Positional Tinkering
|
||||
vs_uniform_block_data.data.vr_position = position;
|
||||
vs_uniform_block_data.dirty = true;
|
||||
static void MatrixMultiply(float m[16], const float a[16], const float b[16]) {
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
m[i * 4 + j] = a[j] * b[i*4] + a[j+4] * b[i*4+1] + a[j+8] * b[i*4+2] + a[j+12] * b[i*4+3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerAccelerated::ApplyVRDataToPicaVSUniforms(Pica::Shader::Generator::VSPicaUniformData &vs_uniforms)
|
||||
{
|
||||
if (vr_immersive_mode)
|
||||
{
|
||||
auto &f = vs_uniforms.uniforms.f;
|
||||
|
||||
int viewMatrixIndex = -1;
|
||||
int mode = vr_immersive_mode;
|
||||
int matrixMode = vr_immersive_mode;
|
||||
if (vr_immersive_mode > 9)
|
||||
{
|
||||
mode = vr_immersive_mode / 10;
|
||||
matrixMode = vr_immersive_mode % 10;
|
||||
}
|
||||
switch (mode)
|
||||
{
|
||||
//OOT / MM specific
|
||||
case 3:
|
||||
if (vs_uniforms.uniforms.bools[1].b != 0 // this is essential
|
||||
&& f[0][3] != 1.0) // This fixes the HUD
|
||||
{
|
||||
viewMatrixIndex = 4;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
viewMatrixIndex = Settings::values.vr_si_mode_register_offset.GetValue();
|
||||
break;
|
||||
case 9:
|
||||
//TEST MODE
|
||||
viewMatrixIndex = vr_uoffset;
|
||||
break;
|
||||
default:
|
||||
viewMatrixIndex = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (viewMatrixIndex != -1 && vs_uniforms.uniforms.f.size() > viewMatrixIndex)
|
||||
{
|
||||
if (matrixMode == 3)
|
||||
{
|
||||
f[viewMatrixIndex][0] = vr_view[0];
|
||||
f[viewMatrixIndex][1] = vr_view[4];
|
||||
f[viewMatrixIndex][2] = vr_view[8];
|
||||
f[viewMatrixIndex + 1][0] = vr_view[1];
|
||||
f[viewMatrixIndex + 1][1] = vr_view[5];
|
||||
f[viewMatrixIndex + 1][2] = vr_view[9];
|
||||
f[viewMatrixIndex + 2][0] = vr_view[2];
|
||||
f[viewMatrixIndex + 2][1] = vr_view[6];
|
||||
f[viewMatrixIndex + 2][2] = vr_view[10];
|
||||
}
|
||||
else if (matrixMode >= 4)
|
||||
{
|
||||
float v[16], v2[16], v3[16];
|
||||
MatrixTranspose(v, &f[viewMatrixIndex].x);
|
||||
std::memcpy(v2, vr_view, sizeof(float) * 16);
|
||||
v2[12] = v2[13] = v2[14] = 0.f;
|
||||
MatrixMultiply(v3, v2, v);
|
||||
MatrixTranspose(&f[viewMatrixIndex].x, v3);
|
||||
}
|
||||
|
||||
f[viewMatrixIndex][3] += vr_view[12];
|
||||
f[viewMatrixIndex + 1][3] += vr_view[13];
|
||||
f[viewMatrixIndex + 2][3] += vr_view[14];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace VideoCore
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
void NotifyPicaRegisterChanged(u32 id) override;
|
||||
void SyncEntireState() override;
|
||||
|
||||
void SetVRData(Common::Vec3f position) override;
|
||||
void SetVRData(const int32_t &vrImmersiveMode, const float& immersiveModeFactor, int uoffset, const float view[16]) override;
|
||||
|
||||
protected:
|
||||
/// Sync fixed-function pipeline state
|
||||
|
@ -105,9 +105,6 @@ protected:
|
|||
/// Syncs the clip plane state to match the PICA register
|
||||
void SyncClipPlane();
|
||||
|
||||
/// Syncs the VR data
|
||||
void SyncVRData();
|
||||
|
||||
protected:
|
||||
/// Structure that keeps tracks of the vertex shader uniform state
|
||||
struct VSUniformBlockData {
|
||||
|
@ -170,5 +167,14 @@ protected:
|
|||
std::array<Common::Vec2f, 128> proctex_alpha_map_data{};
|
||||
std::array<Common::Vec4f, 256> proctex_lut_data{};
|
||||
std::array<Common::Vec4f, 256> proctex_diff_lut_data{};
|
||||
|
||||
//VR Stuff
|
||||
u32 vr_uoffset = -1;
|
||||
u32 vr_immersive_mode;
|
||||
float vr_view[16] = {};
|
||||
|
||||
public:
|
||||
|
||||
void ApplyVRDataToPicaVSUniforms(Pica::Shader::Generator::VSPicaUniformData &vs_uniforms);
|
||||
};
|
||||
} // namespace VideoCore
|
||||
|
|
|
@ -84,6 +84,6 @@ public:
|
|||
virtual void SyncEntireState() {}
|
||||
|
||||
/// Set VR position data on the rasterizer
|
||||
virtual void SetVRData(Common::Vec3f position) {}
|
||||
virtual void SetVRData(const int32_t &vrImmersiveMode, const float& immersiveModeFactor, int uoffset, const float view[16]) {}
|
||||
};
|
||||
} // namespace VideoCore
|
||||
|
|
|
@ -434,9 +434,6 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
|
|||
SyncAndUploadLUTs();
|
||||
SyncAndUploadLUTsLF();
|
||||
|
||||
//Sync VR data if needed
|
||||
SyncVRData();
|
||||
|
||||
// Sync the uniform data
|
||||
UploadUniforms(accelerate);
|
||||
|
||||
|
@ -1133,6 +1130,9 @@ void RasterizerOpenGL::UploadUniforms(bool accelerate_draw) {
|
|||
if (sync_vs_pica) {
|
||||
VSPicaUniformData vs_uniforms;
|
||||
vs_uniforms.uniforms.SetFromRegs(regs.vs, Pica::g_state.vs);
|
||||
|
||||
ApplyVRDataToPicaVSUniforms(vs_uniforms);
|
||||
|
||||
std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms));
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, UniformBindings::VSPicaData,
|
||||
uniform_buffer.GetHandle(), offset + used_bytes, sizeof(vs_uniforms));
|
||||
|
|
|
@ -1133,6 +1133,9 @@ void RasterizerVulkan::UploadUniforms(bool accelerate_draw) {
|
|||
if (sync_vs_pica) {
|
||||
VSPicaUniformData vs_uniforms;
|
||||
vs_uniforms.uniforms.SetFromRegs(regs.vs, Pica::g_state.vs);
|
||||
|
||||
ApplyVRDataToPicaVSUniforms(vs_uniforms);
|
||||
|
||||
std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms));
|
||||
|
||||
pipeline_cache.SetBufferOffset(0, offset + used_bytes);
|
||||
|
|
|
@ -47,7 +47,6 @@ layout (binding = 1, std140) uniform vs_data {
|
|||
vec4 clip_coef;
|
||||
|
||||
float vr_immersive_mode_factor;
|
||||
vec3 vr_position;
|
||||
};
|
||||
)";
|
||||
|
||||
|
@ -1642,12 +1641,13 @@ do {
|
|||
return out;
|
||||
}
|
||||
|
||||
|
||||
static std::string GenerateGLPositionAndGLClipDistanceBlock(bool use_clip_planes)
|
||||
{
|
||||
std::string out;
|
||||
|
||||
out+= "\n gl_Position = vec4(vtx_pos.x / vr_immersive_mode_factor + vr_position.x, vtx_pos.y / vr_immersive_mode_factor + vr_position.y, -vtx_pos.z - vr_position.z, vtx_pos.w - vr_position.z);\n";
|
||||
out += R"(
|
||||
gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);
|
||||
gl_Position.xy /= vr_immersive_mode_factor;
|
||||
)";
|
||||
|
||||
if (use_clip_planes)
|
||||
{
|
||||
|
@ -1706,7 +1706,22 @@ void main() {
|
|||
}
|
||||
)";
|
||||
|
||||
out += GenerateGLPositionAndGLClipDistanceBlock(use_clip_planes);
|
||||
out += R"(
|
||||
gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);
|
||||
gl_Position.xy /= vr_immersive_mode_factor;
|
||||
)";
|
||||
|
||||
if (use_clip_planes)
|
||||
{
|
||||
out += R"(
|
||||
gl_ClipDistance[0] = -vtx_pos.z; // fixed PICA clipping plane z <= 0
|
||||
if (enable_clip1) {
|
||||
gl_ClipDistance[1] = dot(clip_coef, vtx_pos);
|
||||
} else {
|
||||
gl_ClipDistance[1] = 0.0;
|
||||
}
|
||||
)";
|
||||
}
|
||||
|
||||
out += "}\n";
|
||||
|
||||
|
@ -1814,7 +1829,22 @@ std::string GenerateVertexShader(const Pica::Shader::ShaderSetup& setup, const P
|
|||
out += " vtx_pos.z = 0.f;\n";
|
||||
out += " }\n";
|
||||
|
||||
out += GenerateGLPositionAndGLClipDistanceBlock(config.state.use_clip_planes);
|
||||
out += R"(
|
||||
gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);
|
||||
gl_Position.xy /= vr_immersive_mode_factor;
|
||||
)";
|
||||
|
||||
if (config.state.use_clip_planes)
|
||||
{
|
||||
out += R"(
|
||||
gl_ClipDistance[0] = -vtx_pos.z; // fixed PICA clipping plane z <= 0
|
||||
if (enable_clip1) {
|
||||
gl_ClipDistance[1] = dot(clip_coef, vtx_pos);
|
||||
} else {
|
||||
gl_ClipDistance[1] = 0.0;
|
||||
}
|
||||
)";
|
||||
}
|
||||
|
||||
out += " normquat = GetVertexQuaternion();\n";
|
||||
out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " +
|
||||
|
|
|
@ -94,9 +94,8 @@ struct VSUniformData {
|
|||
|
||||
//VR data at the end to ensure it doesn't interfere with existing uniforms' alignment
|
||||
alignas(4) float vr_immersive_mode_factor;
|
||||
alignas(16) Common::Vec3f vr_position;
|
||||
};
|
||||
static_assert(sizeof(VSUniformData) == 64,
|
||||
static_assert(sizeof(VSUniformData) == 48,
|
||||
"The size of the VSUniformData does not match the structure in the shader");
|
||||
static_assert(sizeof(VSUniformData) < 16384,
|
||||
"VSUniformData structure must be less than 16kb as per the OpenGL spec");
|
||||
|
|
Loading…
Reference in a new issue