mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-01 13:17:20 +02:00
Add Clarity boost mode
This commit is contained in:
parent
e502e49d64
commit
3290a36886
38
dist/better-xcloud.pretty.user.js
vendored
38
dist/better-xcloud.pretty.user.js
vendored
@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name Better xCloud
|
||||
// @namespace https://github.com/redphx
|
||||
// @version 6.5.0
|
||||
// @version 6.5.1-beta
|
||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||
// @author redphx
|
||||
// @license MIT
|
||||
@ -120,6 +120,7 @@ var ALL_PREFS = {
|
||||
"video.position",
|
||||
"video.player.powerPreference",
|
||||
"video.processing",
|
||||
"video.processing.mode",
|
||||
"video.ratio",
|
||||
"video.saturation",
|
||||
"video.processing.sharpness"
|
||||
@ -192,7 +193,7 @@ class UserAgent {
|
||||
});
|
||||
}
|
||||
}
|
||||
var SCRIPT_VERSION = "6.5.0", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
||||
var SCRIPT_VERSION = "6.5.1-beta", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
||||
UserAgent.init();
|
||||
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
||||
supportedRegion: !0,
|
||||
@ -874,7 +875,9 @@ class Translations {
|
||||
localStorage.setItem(Translations.KEY_LOCALE, locale);
|
||||
}
|
||||
}
|
||||
var t = Translations.get;
|
||||
var t = Translations.get, ut = (text) => {
|
||||
return BxLogger.warning("Untranslated text", text), text;
|
||||
};
|
||||
Translations.init();
|
||||
class NavigationUtils {
|
||||
static setNearby($elm, nearby) {
|
||||
@ -2395,6 +2398,18 @@ class StreamSettingsStorage extends BaseSettingsStorage {
|
||||
highest: "cas"
|
||||
}
|
||||
},
|
||||
"video.processing.mode": {
|
||||
label: ut("clarity-boost-mode"),
|
||||
default: "performance",
|
||||
options: {
|
||||
quality: ut("quality"),
|
||||
performance: ut("performance")
|
||||
},
|
||||
suggest: {
|
||||
lowest: "performance",
|
||||
highest: "quality"
|
||||
}
|
||||
},
|
||||
"video.player.powerPreference": {
|
||||
label: t("renderer-configuration"),
|
||||
default: "default",
|
||||
@ -4415,6 +4430,10 @@ class SettingsManager {
|
||||
}
|
||||
},
|
||||
"video.processing": {
|
||||
onChange: updateVideoPlayer,
|
||||
onChangeUi: onChangeVideoPlayerType
|
||||
},
|
||||
"video.processing.mode": {
|
||||
onChange: updateVideoPlayer
|
||||
},
|
||||
"video.processing.sharpness": {
|
||||
@ -4565,13 +4584,13 @@ class SettingsManager {
|
||||
}
|
||||
}
|
||||
function onChangeVideoPlayerType() {
|
||||
let playerType = getStreamPref("video.player.type"), settingsManager = SettingsManager.getInstance();
|
||||
let playerType = getStreamPref("video.player.type"), processing = getStreamPref("video.processing"), settingsManager = SettingsManager.getInstance();
|
||||
if (!settingsManager.hasElement("video.processing")) return;
|
||||
let isDisabled = !1, $videoProcessing = settingsManager.getElement("video.processing"), $videoSharpness = settingsManager.getElement("video.processing.sharpness"), $videoPowerPreference = settingsManager.getElement("video.player.powerPreference"), $videoMaxFps = settingsManager.getElement("video.maxFps"), $optCas = $videoProcessing.querySelector(`option[value=${"cas"}]`);
|
||||
let isDisabled = !1, $videoProcessing = settingsManager.getElement("video.processing"), $videoProcessingMode = settingsManager.getElement("video.processing.mode"), $videoSharpness = settingsManager.getElement("video.processing.sharpness"), $videoPowerPreference = settingsManager.getElement("video.player.powerPreference"), $videoMaxFps = settingsManager.getElement("video.maxFps"), $optCas = $videoProcessing.querySelector(`option[value=${"cas"}]`);
|
||||
if (playerType === "default") {
|
||||
if ($videoProcessing.value = "usm", setStreamPref("video.processing", "usm", "direct"), $optCas && ($optCas.disabled = !0), UserAgent.isSafari()) isDisabled = !0;
|
||||
} else $optCas && ($optCas.disabled = !1);
|
||||
$videoProcessing.disabled = isDisabled, $videoSharpness.dataset.disabled = isDisabled.toString(), $videoPowerPreference.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType === "default");
|
||||
$videoProcessing.disabled = isDisabled, $videoSharpness.dataset.disabled = isDisabled.toString(), $videoProcessingMode.closest(".bx-settings-row").classList.toggle("bx-gone", !(playerType === "webgl2" && processing === "cas")), $videoPowerPreference.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType === "default");
|
||||
}
|
||||
function limitVideoPlayerFps(targetFps) {
|
||||
STATES.currentStream.streamPlayerManager?.getCanvasPlayer()?.setTargetFps(targetFps);
|
||||
@ -4581,6 +4600,7 @@ function updateVideoPlayer() {
|
||||
if (!streamPlayerManager) return;
|
||||
let options = {
|
||||
processing: getStreamPref("video.processing"),
|
||||
processingMode: getStreamPref("video.processing.mode"),
|
||||
sharpness: getStreamPref("video.processing.sharpness"),
|
||||
saturation: getStreamPref("video.saturation"),
|
||||
contrast: getStreamPref("video.contrast"),
|
||||
@ -7393,6 +7413,7 @@ class SettingsDialog extends NavigationDialog {
|
||||
"video.maxFps",
|
||||
"video.player.powerPreference",
|
||||
"video.processing",
|
||||
"video.processing.mode",
|
||||
"video.ratio",
|
||||
"video.position",
|
||||
"video.processing.sharpness",
|
||||
@ -9382,7 +9403,7 @@ class WebGL2Player extends BaseCanvasPlayer {
|
||||
updateCanvas() {
|
||||
console.log("updateCanvas", this.options);
|
||||
let gl = this.gl, program = this.program, filterId = this.toFilterId(this.options.processing);
|
||||
gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), filterId), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpness), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness / 100), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast / 100), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation / 100);
|
||||
gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), filterId), gl.uniform1i(gl.getUniformLocation(program, "qualityMode"), this.options.processingMode === "quality" ? 1 : 0), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpness / (this.options.processingMode === "quality" ? 1 : 1.2)), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness / 100), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast / 100), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation / 100);
|
||||
}
|
||||
updateFrame() {
|
||||
let gl = this.gl;
|
||||
@ -9404,7 +9425,7 @@ class WebGL2Player extends BaseCanvasPlayer {
|
||||
in vec4 position;void main() {gl_Position = position;}`), gl.compileShader(vShader);
|
||||
let fShader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
gl.shaderSource(fShader, `#version 300 es
|
||||
precision mediump float;uniform sampler2D data;uniform vec2 iResolution;const int FILTER_UNSHARP_MASKING = 1;const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;const vec3 LUMINOSITY_FACTOR = vec3(0.299, 0.587, 0.114);uniform int filterId;uniform float sharpenFactor;uniform float brightness;uniform float contrast;uniform float saturation;out vec4 fragColor;vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {vec2 texelSize = 1.0 / iResolution.xy;vec3 a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;vec3 b = texture(tex, coord + texelSize * vec2(0, 1)).rgb;vec3 c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;vec3 d = texture(tex, coord + texelSize * vec2(-1, 0)).rgb;vec3 f = texture(tex, coord + texelSize * vec2(1, 0)).rgb;vec3 g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;vec3 h = texture(tex, coord + texelSize * vec2(0, -1)).rgb;vec3 i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;if (filterId == FILTER_UNSHARP_MASKING) {vec3 gaussianBlur = (a + c + g + i) * 1.0 + (b + d + f + h) * 2.0 + e * 4.0;gaussianBlur /= 16.0;return e + (e - gaussianBlur) * sharpenFactor / 3.0;}vec3 minRgb = min(min(min(d, e), min(f, b)), h);minRgb += min(min(a, c), min(g, i));vec3 maxRgb = max(max(max(d, e), max(f, b)), h);maxRgb += max(max(a, c), max(g, i));vec3 reciprocalMaxRgb = 1.0 / maxRgb;vec3 amplifyRgb = clamp(min(minRgb, 2.0 - maxRgb) * reciprocalMaxRgb, 0.0, 1.0);amplifyRgb = inversesqrt(amplifyRgb);vec3 weightRgb = -(1.0 / (amplifyRgb * CAS_CONTRAST_PEAK));vec3 reciprocalWeightRgb = 1.0 / (4.0 * weightRgb + 1.0);vec3 window = b + d + f + h;vec3 outColor = clamp((window * weightRgb + e) * reciprocalWeightRgb, 0.0, 1.0);return mix(e, outColor, sharpenFactor / 2.0);}void main() {vec2 uv = gl_FragCoord.xy / iResolution.xy;vec3 color = texture(data, uv).rgb;color = sharpenFactor > 0.0 ? clarityBoost(data, uv, color) : color;color = saturation != 1.0 ? mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation) : color;color = contrast * (color - 0.5) + 0.5;color = brightness * color;fragColor = vec4(color, 1.0);}`), gl.compileShader(fShader);
|
||||
precision mediump float;uniform sampler2D data;uniform vec2 iResolution;const int FILTER_UNSHARP_MASKING = 1;const int FILTER_CAS = 2;const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;const vec3 LUMINOSITY_FACTOR = vec3(0.299, 0.587, 0.114);uniform int filterId;uniform bool qualityMode;uniform float sharpenFactor;uniform float brightness;uniform float contrast;uniform float saturation;out vec4 fragColor;vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {vec2 texelSize = 1.0 / iResolution.xy;vec3 b = texture(tex, coord + texelSize * vec2(0, 1)).rgb;vec3 d = texture(tex, coord + texelSize * vec2(-1, 0)).rgb;vec3 f = texture(tex, coord + texelSize * vec2(1, 0)).rgb;vec3 h = texture(tex, coord + texelSize * vec2(0, -1)).rgb;vec3 a;vec3 c;vec3 g;vec3 i;if (filterId == FILTER_UNSHARP_MASKING || qualityMode) {a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;}if (filterId == FILTER_UNSHARP_MASKING) {vec3 gaussianBlur = (a + c + g + i) * 1.0 + (b + d + f + h) * 2.0 + e * 4.0;gaussianBlur /= 16.0;return e + (e - gaussianBlur) * sharpenFactor / 3.0;}vec3 minRgb = min(min(min(d, e), min(f, b)), h);vec3 maxRgb = max(max(max(d, e), max(f, b)), h);if (qualityMode) {minRgb += min(min(a, c), min(g, i));maxRgb += max(max(a, c), max(g, i));}vec3 reciprocalMaxRgb = 1.0 / maxRgb;vec3 amplifyRgb = clamp(min(minRgb, 2.0 - maxRgb) * reciprocalMaxRgb, 0.0, 1.0);amplifyRgb = inversesqrt(amplifyRgb);vec3 weightRgb = -(1.0 / (amplifyRgb * CAS_CONTRAST_PEAK));vec3 reciprocalWeightRgb = 1.0 / (4.0 * weightRgb + 1.0);vec3 window = b + d + f + h;vec3 outColor = clamp((window * weightRgb + e) * reciprocalWeightRgb, 0.0, 1.0);return mix(e, outColor, sharpenFactor / 2.0);}void main() {vec2 uv = gl_FragCoord.xy / iResolution.xy;vec3 color = texture(data, uv).rgb;if (sharpenFactor > 0.0) {color = clarityBoost(data, uv, color);}color = mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation);color = contrast * (color - 0.5) + 0.5;color = brightness * color;fragColor = vec4(color, 1.0);}`), gl.compileShader(fShader);
|
||||
let program = gl.createProgram();
|
||||
if (this.program = program, gl.attachShader(program, vShader), gl.attachShader(program, fShader), gl.linkProgram(program), gl.useProgram(program), !gl.getProgramParameter(program, gl.LINK_STATUS)) console.error(`Link failed: ${gl.getProgramInfoLog(program)}`), console.error(`vs info-log: ${gl.getShaderInfoLog(vShader)}`), console.error(`fs info-log: ${gl.getShaderInfoLog(fShader)}`);
|
||||
this.updateCanvas();
|
||||
@ -9567,6 +9588,7 @@ function patchVideoApi() {
|
||||
if (this.style.visibility = "visible", !this.videoWidth) return;
|
||||
let playerOptions = {
|
||||
processing: getStreamPref("video.processing"),
|
||||
processingMode: getStreamPref("video.processing.mode"),
|
||||
sharpness: getStreamPref("video.processing.sharpness"),
|
||||
saturation: getStreamPref("video.saturation"),
|
||||
contrast: getStreamPref("video.contrast"),
|
||||
|
24
dist/better-xcloud.user.js
vendored
24
dist/better-xcloud.user.js
vendored
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
import type { BaseSettingsStorage } from "@/utils/settings-storages/base-settings-storage";
|
||||
import type { BlockFeature, CodecProfile, DeviceVibrationMode, GameBarPosition, LoadingScreenRocket, NativeMkbMode, StreamPlayerType, StreamResolution, StreamStat, StreamStatPosition, StreamVideoProcessing, TouchControllerMode, TouchControllerStyleCustom, TouchControllerStyleStandard, UiLayout, UiSection, UiTheme, VideoPosition, VideoPowerPreference, VideoRatio } from "./pref-values"
|
||||
import type { BlockFeature, CodecProfile, DeviceVibrationMode, GameBarPosition, LoadingScreenRocket, NativeMkbMode, StreamPlayerType, StreamResolution, StreamStat, StreamStatPosition, StreamVideoProcessing, StreamVideoProcessingMode, TouchControllerMode, TouchControllerStyleCustom, TouchControllerStyleStandard, UiLayout, UiSection, UiTheme, VideoPosition, VideoPowerPreference, VideoRatio } from "./pref-values"
|
||||
|
||||
export const enum StorageKey {
|
||||
GLOBAL = 'BetterXcloud',
|
||||
@ -156,6 +156,7 @@ export const enum StreamPref {
|
||||
VIDEO_PLAYER_TYPE = 'video.player.type',
|
||||
VIDEO_POWER_PREFERENCE = 'video.player.powerPreference',
|
||||
VIDEO_PROCESSING = 'video.processing',
|
||||
VIDEO_PROCESSING_MODE = 'video.processing.mode',
|
||||
VIDEO_SHARPNESS = 'video.processing.sharpness',
|
||||
VIDEO_MAX_FPS = 'video.maxFps',
|
||||
VIDEO_RATIO = 'video.ratio',
|
||||
@ -205,6 +206,7 @@ export type StreamPrefTypeMap = {
|
||||
[StreamPref.VIDEO_POSITION]: VideoPosition;
|
||||
[StreamPref.VIDEO_POWER_PREFERENCE]: VideoPowerPreference;
|
||||
[StreamPref.VIDEO_PROCESSING]: StreamVideoProcessing;
|
||||
[StreamPref.VIDEO_PROCESSING_MODE]: StreamVideoProcessingMode;
|
||||
[StreamPref.VIDEO_RATIO]: VideoRatio;
|
||||
[StreamPref.VIDEO_SATURATION]: number;
|
||||
[StreamPref.VIDEO_SHARPNESS]: number;
|
||||
@ -294,6 +296,7 @@ export const ALL_PREFS: {
|
||||
StreamPref.VIDEO_POSITION,
|
||||
StreamPref.VIDEO_POWER_PREFERENCE,
|
||||
StreamPref.VIDEO_PROCESSING,
|
||||
StreamPref.VIDEO_PROCESSING_MODE,
|
||||
StreamPref.VIDEO_RATIO,
|
||||
StreamPref.VIDEO_SATURATION,
|
||||
StreamPref.VIDEO_SHARPNESS,
|
||||
|
@ -130,6 +130,11 @@ export const enum StreamVideoProcessing {
|
||||
CAS = 'cas',
|
||||
}
|
||||
|
||||
export const enum StreamVideoProcessingMode {
|
||||
QUALITY = 'quality',
|
||||
PERFORMANCE = 'performance',
|
||||
}
|
||||
|
||||
export const enum BlockFeature {
|
||||
CHAT = 'chat',
|
||||
FRIENDS = 'friends',
|
||||
|
@ -5,7 +5,7 @@ uniform sampler2D data;
|
||||
uniform vec2 iResolution;
|
||||
|
||||
const int FILTER_UNSHARP_MASKING = 1;
|
||||
// const int FILTER_CAS = 2;
|
||||
const int FILTER_CAS = 2;
|
||||
|
||||
// constrast = 0.8
|
||||
const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;
|
||||
@ -14,6 +14,7 @@ const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;
|
||||
const vec3 LUMINOSITY_FACTOR = vec3(0.299, 0.587, 0.114);
|
||||
|
||||
uniform int filterId;
|
||||
uniform bool qualityMode;
|
||||
uniform float sharpenFactor;
|
||||
uniform float brightness;
|
||||
uniform float contrast;
|
||||
@ -28,16 +29,22 @@ vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {
|
||||
// a b c
|
||||
// d e f
|
||||
// g h i
|
||||
vec3 a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;
|
||||
vec3 b = texture(tex, coord + texelSize * vec2(0, 1)).rgb;
|
||||
vec3 c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;
|
||||
|
||||
vec3 d = texture(tex, coord + texelSize * vec2(-1, 0)).rgb;
|
||||
vec3 f = texture(tex, coord + texelSize * vec2(1, 0)).rgb;
|
||||
|
||||
vec3 g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;
|
||||
vec3 h = texture(tex, coord + texelSize * vec2(0, -1)).rgb;
|
||||
vec3 i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;
|
||||
|
||||
vec3 a;
|
||||
vec3 c;
|
||||
vec3 g;
|
||||
vec3 i;
|
||||
|
||||
if (filterId == FILTER_UNSHARP_MASKING || qualityMode) {
|
||||
a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;
|
||||
c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;
|
||||
g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;
|
||||
i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;
|
||||
}
|
||||
|
||||
// USM
|
||||
if (filterId == FILTER_UNSHARP_MASKING) {
|
||||
@ -55,10 +62,12 @@ vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {
|
||||
// g h i h
|
||||
// These are 2.0x bigger (factored out the extra multiply).
|
||||
vec3 minRgb = min(min(min(d, e), min(f, b)), h);
|
||||
minRgb += min(min(a, c), min(g, i));
|
||||
|
||||
vec3 maxRgb = max(max(max(d, e), max(f, b)), h);
|
||||
maxRgb += max(max(a, c), max(g, i));
|
||||
|
||||
if (qualityMode) {
|
||||
minRgb += min(min(a, c), min(g, i));
|
||||
maxRgb += max(max(a, c), max(g, i));
|
||||
}
|
||||
|
||||
// Smooth minimum distance to signal limit divided by smooth max.
|
||||
vec3 reciprocalMaxRgb = 1.0 / maxRgb;
|
||||
@ -85,10 +94,12 @@ void main() {
|
||||
vec3 color = texture(data, uv).rgb;
|
||||
|
||||
// Clarity boost
|
||||
color = sharpenFactor > 0.0 ? clarityBoost(data, uv, color) : color;
|
||||
if (sharpenFactor > 0.0) {
|
||||
color = clarityBoost(data, uv, color);
|
||||
}
|
||||
|
||||
// Saturation
|
||||
color = saturation != 1.0 ? mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation) : color;
|
||||
color = mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation);
|
||||
|
||||
// Contrast
|
||||
color = contrast * (color - 0.5) + 0.5;
|
||||
|
@ -3,7 +3,7 @@ import { compressCodeFile } from "@macros/build" with { type: "macro" };
|
||||
import { StreamPref } from "@/enums/pref-keys";
|
||||
import { getStreamPref } from "@/utils/pref-utils";
|
||||
import { BaseCanvasPlayer } from "../base-canvas-player";
|
||||
import { StreamPlayerType } from "@/enums/pref-values";
|
||||
import { StreamPlayerType, StreamVideoProcessingMode } from "@/enums/pref-values";
|
||||
|
||||
|
||||
export class WebGL2Player extends BaseCanvasPlayer {
|
||||
@ -25,7 +25,8 @@ export class WebGL2Player extends BaseCanvasPlayer {
|
||||
gl.uniform2f(gl.getUniformLocation(program, 'iResolution'), this.$canvas.width, this.$canvas.height);
|
||||
|
||||
gl.uniform1i(gl.getUniformLocation(program, 'filterId'), filterId);
|
||||
gl.uniform1f(gl.getUniformLocation(program, 'sharpenFactor'), this.options.sharpness);
|
||||
gl.uniform1i(gl.getUniformLocation(program, 'qualityMode'), this.options.processingMode === StreamVideoProcessingMode.QUALITY ? 1 : 0);
|
||||
gl.uniform1f(gl.getUniformLocation(program, 'sharpenFactor'), this.options.sharpness / (this.options.processingMode === StreamVideoProcessingMode.QUALITY ? 1 : 1.2));
|
||||
gl.uniform1f(gl.getUniformLocation(program, 'brightness'), this.options.brightness / 100);
|
||||
gl.uniform1f(gl.getUniformLocation(program, 'contrast'), this.options.contrast / 100);
|
||||
gl.uniform1f(gl.getUniformLocation(program, 'saturation'), this.options.saturation / 100);
|
||||
|
@ -82,6 +82,10 @@ export class SettingsManager {
|
||||
},
|
||||
[StreamPref.VIDEO_PROCESSING]: {
|
||||
onChange: updateVideoPlayer,
|
||||
onChangeUi: onChangeVideoPlayerType,
|
||||
},
|
||||
[StreamPref.VIDEO_PROCESSING_MODE]: {
|
||||
onChange: updateVideoPlayer,
|
||||
},
|
||||
[StreamPref.VIDEO_SHARPNESS]: {
|
||||
onChange: updateVideoPlayer,
|
||||
|
@ -8,6 +8,7 @@ import type { StreamPlayerOptions } from "@/types/stream";
|
||||
|
||||
export function onChangeVideoPlayerType() {
|
||||
const playerType = getStreamPref(StreamPref.VIDEO_PLAYER_TYPE);
|
||||
const processing = getStreamPref(StreamPref.VIDEO_PROCESSING);
|
||||
const settingsManager = SettingsManager.getInstance();
|
||||
if (!settingsManager.hasElement(StreamPref.VIDEO_PROCESSING)) {
|
||||
return;
|
||||
@ -16,6 +17,7 @@ export function onChangeVideoPlayerType() {
|
||||
let isDisabled = false;
|
||||
|
||||
const $videoProcessing = settingsManager.getElement(StreamPref.VIDEO_PROCESSING) as HTMLSelectElement;
|
||||
const $videoProcessingMode = settingsManager.getElement(StreamPref.VIDEO_PROCESSING_MODE) as HTMLSelectElement;
|
||||
const $videoSharpness = settingsManager.getElement(StreamPref.VIDEO_SHARPNESS);
|
||||
const $videoPowerPreference = settingsManager.getElement(StreamPref.VIDEO_POWER_PREFERENCE);
|
||||
const $videoMaxFps = settingsManager.getElement(StreamPref.VIDEO_MAX_FPS);
|
||||
@ -40,6 +42,7 @@ export function onChangeVideoPlayerType() {
|
||||
$videoSharpness.dataset.disabled = isDisabled.toString();
|
||||
|
||||
// Hide Power Preference setting if renderer isn't WebGL2
|
||||
$videoProcessingMode.closest('.bx-settings-row')!.classList.toggle('bx-gone', !(playerType === StreamPlayerType.WEBGL2 && processing === StreamVideoProcessing.CAS));
|
||||
$videoPowerPreference.closest('.bx-settings-row')!.classList.toggle('bx-gone', playerType !== StreamPlayerType.WEBGL2);
|
||||
$videoMaxFps.closest('.bx-settings-row')!.classList.toggle('bx-gone', playerType === StreamPlayerType.VIDEO);
|
||||
}
|
||||
@ -59,6 +62,7 @@ export function updateVideoPlayer() {
|
||||
|
||||
const options = {
|
||||
processing: getStreamPref(StreamPref.VIDEO_PROCESSING),
|
||||
processingMode: getStreamPref(StreamPref.VIDEO_PROCESSING_MODE),
|
||||
sharpness: getStreamPref(StreamPref.VIDEO_SHARPNESS),
|
||||
saturation: getStreamPref(StreamPref.VIDEO_SATURATION),
|
||||
contrast: getStreamPref(StreamPref.VIDEO_CONTRAST),
|
||||
|
@ -452,6 +452,7 @@ export class SettingsDialog extends NavigationDialog {
|
||||
StreamPref.VIDEO_MAX_FPS,
|
||||
StreamPref.VIDEO_POWER_PREFERENCE,
|
||||
StreamPref.VIDEO_PROCESSING,
|
||||
StreamPref.VIDEO_PROCESSING_MODE,
|
||||
StreamPref.VIDEO_RATIO,
|
||||
StreamPref.VIDEO_POSITION,
|
||||
StreamPref.VIDEO_SHARPNESS,
|
||||
|
3
src/types/stream.d.ts
vendored
3
src/types/stream.d.ts
vendored
@ -1,7 +1,8 @@
|
||||
import type { StreamVideoProcessing } from "@/enums/pref-values";
|
||||
import type { StreamVideoProcessing, StreamVideoProcessingMode } from "@/enums/pref-values";
|
||||
|
||||
type StreamPlayerOptions = {
|
||||
processing: StreamVideoProcessing,
|
||||
processingMode: StreamVideoProcessingMode,
|
||||
sharpness: number,
|
||||
saturation: number,
|
||||
contrast: number,
|
||||
|
@ -22,6 +22,7 @@ export function patchVideoApi() {
|
||||
|
||||
const playerOptions = {
|
||||
processing: getStreamPref(StreamPref.VIDEO_PROCESSING),
|
||||
processingMode: getStreamPref(StreamPref.VIDEO_PROCESSING_MODE),
|
||||
sharpness: getStreamPref(StreamPref.VIDEO_SHARPNESS),
|
||||
saturation: getStreamPref(StreamPref.VIDEO_SATURATION),
|
||||
contrast: getStreamPref(StreamPref.VIDEO_CONTRAST),
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { StreamPref, StorageKey, type PrefTypeMap } from "@/enums/pref-keys";
|
||||
import { DeviceVibrationMode, StreamPlayerType, StreamVideoProcessing, VideoPowerPreference, VideoRatio, VideoPosition, StreamStat, StreamStatPosition } from "@/enums/pref-values";
|
||||
import { DeviceVibrationMode, StreamPlayerType, StreamVideoProcessing, VideoPowerPreference, VideoRatio, VideoPosition, StreamStat, StreamStatPosition, StreamVideoProcessingMode } from "@/enums/pref-values";
|
||||
import { STATES } from "../global";
|
||||
import { KeyboardShortcutDefaultId } from "../local-db/keyboard-shortcuts-table";
|
||||
import { MkbMappingDefaultPresetId } from "../local-db/mkb-mapping-presets-table";
|
||||
import { t } from "../translation";
|
||||
import { t, ut } from "../translation";
|
||||
import { BaseSettingsStorage } from "./base-settings-storage";
|
||||
import { CE } from "../html";
|
||||
import type { SettingActionOrigin, SettingDefinitions } from "@/types/setting-definition";
|
||||
@ -179,6 +179,18 @@ export class StreamSettingsStorage extends BaseSettingsStorage<StreamPref> {
|
||||
highest: StreamVideoProcessing.CAS,
|
||||
},
|
||||
},
|
||||
[StreamPref.VIDEO_PROCESSING_MODE]: {
|
||||
label: ut('clarity-boost-mode'),
|
||||
default: StreamVideoProcessingMode.PERFORMANCE,
|
||||
options: {
|
||||
[StreamVideoProcessingMode.QUALITY]: ut('quality'),
|
||||
[StreamVideoProcessingMode.PERFORMANCE]: ut('performance'),
|
||||
},
|
||||
suggest: {
|
||||
lowest: StreamVideoProcessingMode.PERFORMANCE,
|
||||
highest: StreamVideoProcessingMode.QUALITY,
|
||||
},
|
||||
},
|
||||
[StreamPref.VIDEO_POWER_PREFERENCE]: {
|
||||
label: t('renderer-configuration'),
|
||||
default: VideoPowerPreference.DEFAULT,
|
||||
|
Loading…
x
Reference in New Issue
Block a user