Got proper 6DoF working..

- also allowed depth slider to go to 200% (for 1st person in MK7)
- added in the "look down to show" for the lower panel
This commit is contained in:
Simon 2024-01-30 23:37:05 +00:00
parent d4515d120f
commit e97ca06b3d
7 changed files with 91 additions and 55 deletions

View file

@ -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, 100, "%", 50, factor3d));
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 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));
@ -437,6 +437,7 @@ public final class SettingsFragmentPresenter {
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_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));
}

View file

@ -30,7 +30,7 @@ License : Licensed under GPLv3 or any later version.
namespace {
constexpr float lowerPanelScaleFactor = 0.75f;
constexpr float defaultLowerPanelScaleFactor = 0.75f;
const std::vector<float> immersiveLevelFactor = {1.0f, 5.0f, 3.0f};
@ -232,11 +232,10 @@ GameSurfaceLayer::GameSurfaceLayer(const XrVector3f&& position, JNIEnv* env, job
env_(env), activityObject_(activityObject)
{
assert(immersiveMode_ == 0 || immersiveMode_ == 1);
if (immersiveMode_ > 0) {
ALOGI("Using VR immersive mode {}", immersiveMode_);
topPanelFromWorld_.position.z = lowerPanelFromWorld_.position.z;
lowerPanelFromWorld_.position.y = -1.0f - (0.5f * (immersiveMode_ - 1));
lowerPanelFromWorld_.position.y = -1.0f;
}
const int32_t initializationStatus = Init(activityObject, position, session);
if (initializationStatus < 0) {
@ -335,6 +334,37 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
layers[layerCount++].mQuad = layer;
}
}
/*
* 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.
// twice), but the image is mono. Therefore, take the right half of the
@ -342,7 +372,7 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
// FIXME we waste rendering time rendering both displays. That said, We also
// waste rendering time copying the buffer between runtimes. No time for
// that now!
if (showLowerPanel)
if (lowerPanelScaleFactor > 0.0f)
{
const uint32_t cropHoriz = 90 * resolutionFactor_;
XrCompositionLayerQuad layer = {};
@ -371,8 +401,8 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
layer.pose = lowerPanelFromWorld_;
const auto scale = GetDensityScaleForSize(panelWidth - cropHoriz, -panelHeight,
lowerPanelScaleFactor, resolutionFactor_);
layer.size.width = scale.x;
layer.size.height = scale.y;
layer.size.width = scale.x * lowerPanelScaleFactor;
layer.size.height = scale.y * lowerPanelScaleFactor;
layers[layerCount++].mQuad = layer;
}
}

View file

@ -96,12 +96,12 @@ public:
*
* @param space the XrSpace this layer should be positioned with. The
* center of the layer is placed in the center of the FOV.
* @param headLocation the XrSpaceLocation - the hmd location
* @param layers the array of layers to populate
* @param layerCount the number of layers in the array
* @param visibleLowerPanel whether the lower panel is shown/visible
*/
void Frame(const XrSpace& space, std::vector<XrCompositionLayer>& layers,
uint32_t& layerCount, const bool showLowerPanel) const;
uint32_t& layerCount, const bool visibleLowerPanel) const;
/** Given an origin, direction of a ray,
* returns the coordinates of where the ray will intersects
@ -171,6 +171,11 @@ private:
// - Rendering the top-screen and bottom screen separately.
const uint32_t immersiveMode_;
// Used to nicely present the lower panel when in toggleable mode.
// Instead of it just appearing instantly, it emerges in a hopefully pleasant
// fashion
mutable float lowerPanelScaleFactor = 0.0f;
//============================
// JNI objects
JNIEnv* env_ = nullptr;

View file

@ -487,28 +487,35 @@ private:
gOpenXr->headLocation = {XR_TYPE_SPACE_LOCATION};
OXR(xrLocateSpace(gOpenXr->viewSpace_, gOpenXr->headSpace_, frameState.predictedDisplayTime, &gOpenXr->headLocation));
bool showLowerPanel = false;
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())
{
//I am confused... but GetRollInRadians appears to return pitch
float pitch = XrMath::Quatf::GetRollInRadians(gOpenXr->headLocation.pose.orientation);
//Only use position if it is enabled, and the user is not looking at the lower panel
if ((VRSettings::values.vr_immersive_positional_factor > 0) && (pitch > -0.35f))
{
Common::Vec3f position{-gOpenXr->headLocation.pose.position.y,
gOpenXr->headLocation.pose.position.x,
0.0f}; //gOpenXr->headLocation.pose.position.z}; - For some reason Z doesn't affect the actual Z position!
position *= VRSettings::values.vr_immersive_positional_factor;
VideoCore::g_renderer->Rasterizer()->SetVRData(position);
}
else
if ((VRSettings::values.vr_immersive_positional_factor == 0) ||
(pitch < -0.35f))
{
//Disable position when looking down at the lower panel
Common::Vec3f position = {};
VideoCore::g_renderer->Rasterizer()->SetVRData(position);
showLowerPanel = true;
}
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!
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;
}
}

View file

@ -42,6 +42,7 @@ struct Values {
uint32_t resolution_factor = 0;
int32_t vr_environment = 0;
int32_t vr_immersive_mode = 0;
int32_t vr_immersive_positional_factor = 0;
bool extra_performance_mode_enabled = false;
} extern values;

View file

@ -300,6 +300,7 @@
<string name="vr_extra_performance_mode">VR Extra Performance Mode</string>
<string name="vr_cpu_level">CPU level</string>
<string name="vr_cpu_level_description">Higher levels may improve audio/emulation performance, but will drain the battery faster</string>
<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_immersive_pos_factor_title">Immersive Mode Positional Movement Factor</string>

View file

@ -1642,6 +1642,28 @@ 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";
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;
}
)";
}
return out;
}
std::string GenerateTrivialVertexShader(bool use_clip_planes, bool separable_shader) {
std::string out;
if (separable_shader) {
@ -1684,26 +1706,13 @@ void main() {
}
)";
out+= "\ngl_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);\n";
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 += GenerateGLPositionAndGLClipDistanceBlock(use_clip_planes);
out += "}\n";
return out;
}
std::string_view MakeLoadPrefix(AttribLoadFlags flag) {
if (True(flag & AttribLoadFlags::Float)) {
return "";
@ -1805,16 +1814,7 @@ std::string GenerateVertexShader(const Pica::Shader::ShaderSetup& setup, const P
out += " vtx_pos.z = 0.f;\n";
out += " }\n";
out+= " 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);\n";
if (config.state.use_clip_planes) {
out += " gl_ClipDistance[0] = -vtx_pos.z;\n"; // fixed PICA clipping plane z <= 0
out += " if (enable_clip1) {\n";
out += " gl_ClipDistance[1] = dot(clip_coef, vtx_pos);\n";
out += " } else {\n";
out += " gl_ClipDistance[1] = 0.0;\n";
out += " }\n\n";
}
out += GenerateGLPositionAndGLClipDistanceBlock(config.state.use_clip_planes);
out += " normquat = GetVertexQuaternion();\n";
out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " +
@ -1904,16 +1904,7 @@ struct Vertex {
out += " vtx_pos.z = 0.f;\n";
out += " }\n";
out += " 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);\n";
if (state.use_clip_planes) {
out += " gl_ClipDistance[0] = -vtx_pos.z;\n"; // fixed PICA clipping plane z <= 0
out += " if (enable_clip1) {\n";
out += " gl_ClipDistance[1] = dot(clip_coef, vtx_pos);\n";
out += " } else {\n";
out += " gl_ClipDistance[1] = 0.0;\n";
out += " }\n\n";
}
out += GenerateGLPositionAndGLClipDistanceBlock(state.use_clip_planes);
out += " vec4 vtx_quat = GetVertexQuaternion(vtx);\n";
out += " normquat = mix(vtx_quat, -vtx_quat, bvec4(quats_opposite));\n\n";