Feat : handle settings gracefully
This commit is contained in:
@@ -5,6 +5,7 @@ import ShaderWorker from '~/assets/workers/ShaderWorker?worker'
|
||||
const worker = new ShaderWorker()
|
||||
|
||||
const canvas = ref<HTMLCanvasElement | null>(null)
|
||||
const canvas_resize_temp = ref<HTMLCanvasElement | null>(null)
|
||||
|
||||
export interface Props {
|
||||
colorStart?: [number, number, number]
|
||||
@@ -20,80 +21,80 @@ function initShader() {
|
||||
const offscreen = canvas.value?.transferControlToOffscreen()
|
||||
worker.postMessage({
|
||||
command: "initShader",
|
||||
canvas: offscreen
|
||||
canvas: offscreen,
|
||||
screen: { height: window.innerHeight * devicePixelRatio, width: window.innerWidth * devicePixelRatio, devicePixelRatio },
|
||||
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
|
||||
}, [offscreen])
|
||||
}
|
||||
function safeReloadShader() {
|
||||
reloadShader()
|
||||
if (settingsStore.shaderFramerate == 0) {
|
||||
killShader()
|
||||
}
|
||||
resizeShader()
|
||||
}
|
||||
|
||||
function reloadShader() {
|
||||
const bounds = canvas.value?.getBoundingClientRect()
|
||||
if (!bounds) { return }
|
||||
function recolorShader() {
|
||||
worker.postMessage({
|
||||
command: 'reloadShader',
|
||||
quality: settingsStore.shaderQuality,
|
||||
framerate: settingsStore.shaderFramerate,
|
||||
bounds: { left: bounds.left, bottom: bounds.bottom },
|
||||
screen: { height: window.screen.height, width: window.screen.width, devicePixelRatio },
|
||||
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
|
||||
command: 'recolorShader',
|
||||
colorStart: props.colorStart,
|
||||
colorEnd: props.colorEnd
|
||||
})
|
||||
}
|
||||
|
||||
function resizeShader() {
|
||||
const bounds = canvas.value?.getBoundingClientRect()
|
||||
if (!bounds) { return }
|
||||
worker.postMessage({
|
||||
command: 'changeBounds',
|
||||
bounds: { left: bounds.left, bottom: bounds.bottom },
|
||||
screen: { height: window.screen.height, width: window.screen.width, devicePixelRatio },
|
||||
colorStart: props.colorStart,
|
||||
colorEnd: props.colorEnd
|
||||
command: 'resizeShader',
|
||||
screen: { height: window.innerHeight * devicePixelRatio, width: window.innerWidth * devicePixelRatio, devicePixelRatio },
|
||||
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
|
||||
})
|
||||
}
|
||||
|
||||
function endShader() {
|
||||
function killShader() {
|
||||
worker.postMessage({
|
||||
command: 'killShader'
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => [settingsStore.shaderQuality, settingsStore.shaderFramerate], () => {
|
||||
safeReloadShader()
|
||||
function resumeShader() {
|
||||
worker.postMessage({
|
||||
command: 'resumeShader',
|
||||
shaderOptions: { quality: settingsStore.shaderQuality, framerate: settingsStore.shaderFramerate },
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => [settingsStore.shaderFramerate], () => {
|
||||
if (settingsStore.shaderFramerate == 0) {
|
||||
killShader()
|
||||
return
|
||||
}
|
||||
resumeShader()
|
||||
|
||||
})
|
||||
|
||||
watch(() => [settingsStore.shaderQuality], () => {
|
||||
resizeShader()
|
||||
})
|
||||
|
||||
let has_resized = false
|
||||
watch(() => [props.colorEnd, props.colorStart], () => {
|
||||
if (!has_resized) {
|
||||
has_resized = true
|
||||
nextTick(() => {
|
||||
resizeShader()
|
||||
has_resized = false
|
||||
})
|
||||
}
|
||||
recolorShader()
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
nextTick(() => {
|
||||
recolorShader()
|
||||
initShader()
|
||||
window.addEventListener("resize", resizeShader, true)
|
||||
safeReloadShader()
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("resize", resizeShader)
|
||||
endShader()
|
||||
killShader()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<canvas v-if="settingsStore.shaderQuality != 0" ref="canvas" id="background">test</canvas>
|
||||
<canvas ref="canvas" id="background" :class="{ pixelated: settingsStore.shaderPixelated }" width="480"
|
||||
height="270">test</canvas>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -102,5 +103,10 @@ onUnmounted(() => {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
image-rendering: smooth;
|
||||
}
|
||||
|
||||
#background.pixelated {
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
</style>
|
||||
@@ -6,6 +6,9 @@ export interface Props {
|
||||
isVisible: boolean;
|
||||
}
|
||||
|
||||
const _devicePixelRatio = computed(() => devicePixelRatio)
|
||||
const _window = computed(() => window)
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
})
|
||||
|
||||
@@ -15,10 +18,6 @@ const close = () => {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
watch(() => settingsStore.shaderQuality, async () => {
|
||||
console.log(settingsStore.shaderQuality)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -40,27 +39,28 @@ watch(() => settingsStore.shaderQuality, async () => {
|
||||
<span>Shader Quality</span>
|
||||
</div>
|
||||
<div class="dialog-body">
|
||||
<input type="range" min="0" max="10" v-model="settingsStore.shaderQuality">
|
||||
<input type="range" min="1" max="10" v-model="settingsStore.shaderQuality">
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<span>
|
||||
<template v-if="settingsStore.shaderQuality == 0">
|
||||
Disabled
|
||||
</template>
|
||||
<template v-if="settingsStore.shaderQuality > 0">
|
||||
{{ settingsStore.shaderQuality }}
|
||||
</template>
|
||||
</span>
|
||||
<span>{{ _window.innerWidth * _devicePixelRatio * settingsStore.shaderQuality / 10 }}x{{ _window.innerHeight *
|
||||
_devicePixelRatio * settingsStore.shaderQuality / 10 }}</span>
|
||||
</div>
|
||||
<div class="dialog-header">
|
||||
<span>Shader Framerate</span>
|
||||
</div>
|
||||
<div class="dialog-body">
|
||||
<input type="range" min="10" max="60" step="5" v-model="settingsStore.shaderFramerate"
|
||||
<input type="range" min="0" max="65" step="5" v-model="settingsStore.shaderFramerate"
|
||||
:disabled="settingsStore.shaderQuality == 0">
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<span>{{ settingsStore.shaderFramerate }} fps</span>
|
||||
<span v-if="settingsStore.shaderFramerate == 65">vsync</span>
|
||||
<span v-else>{{ settingsStore.shaderFramerate }} fps</span>
|
||||
</div>
|
||||
<div class="dialog-header">
|
||||
<span>Pixelated</span>
|
||||
</div>
|
||||
<div class="dialog-body">
|
||||
<input type="checkbox" v-model="settingsStore.shaderPixelated">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user