172 lines
3.6 KiB
Vue
172 lines
3.6 KiB
Vue
<script setup lang="ts">
|
|
const settingsStore = useSettingsStore();
|
|
|
|
import gsap from "gsap";
|
|
import ShaderWorker from "~/assets/workers/ShaderWorker?worker";
|
|
import type { Game } from "~/netcode/interfaces";
|
|
|
|
const emit = defineEmits<{
|
|
ready: [];
|
|
}>();
|
|
|
|
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];
|
|
colorEnd?: [number, number, number];
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
colorStart: () => [0, 0.3, 0],
|
|
colorEnd: () => [0, 1, 0],
|
|
});
|
|
|
|
const _colorStart = reactive(props.colorStart);
|
|
const _colorEnd = reactive(props.colorEnd);
|
|
|
|
function initShader() {
|
|
return new Promise<void>((resolve, reject) => {
|
|
if (!canvas.value) {
|
|
reject("canvas is null");
|
|
return;
|
|
}
|
|
const offscreen = canvas.value?.transferControlToOffscreen();
|
|
worker.postMessage(
|
|
{
|
|
command: "initShader",
|
|
canvas: offscreen,
|
|
screen: {
|
|
height: window.innerHeight * devicePixelRatio,
|
|
width: window.innerWidth * devicePixelRatio,
|
|
devicePixelRatio,
|
|
},
|
|
shaderOptions: {
|
|
quality: settingsStore.shaderQuality,
|
|
framerate: settingsStore.shaderFramerate,
|
|
},
|
|
},
|
|
[offscreen]
|
|
);
|
|
if (settingsStore.shaderFramerate == 0) {
|
|
killShader();
|
|
}
|
|
resizeShader();
|
|
worker.onmessage = (e) => {
|
|
if (e.data == "ready") {
|
|
resolve();
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
function recolorShader() {
|
|
worker.postMessage({
|
|
command: "recolorShader",
|
|
colorStart: [..._colorStart],
|
|
colorEnd: [..._colorEnd],
|
|
});
|
|
}
|
|
|
|
function resizeShader() {
|
|
worker.postMessage({
|
|
command: "resizeShader",
|
|
screen: {
|
|
height: window.innerHeight * devicePixelRatio,
|
|
width: window.innerWidth * devicePixelRatio,
|
|
devicePixelRatio,
|
|
},
|
|
shaderOptions: {
|
|
quality: settingsStore.shaderQuality,
|
|
framerate: settingsStore.shaderFramerate,
|
|
},
|
|
});
|
|
}
|
|
|
|
function killShader() {
|
|
worker.postMessage({
|
|
command: "killShader",
|
|
});
|
|
}
|
|
|
|
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();
|
|
}
|
|
);
|
|
|
|
// watch(() => [props.game.currentTurn], () => {
|
|
// if (props.game.teams.find() != goStore.self?.team) {
|
|
// gsap.to(_colorStart, { duration: 0.5, 0: 0, 1: .2, 2: .3 })
|
|
// gsap.to(_colorEnd, { duration: 0.5, 0: 0, 1: 1, 2: 1 })
|
|
// } else {
|
|
// gsap.to(_colorStart, { duration: 0.5, 0: 0, 1: .3, 2: 0 })
|
|
// gsap.to(_colorEnd, { duration: 0.5, 0: 0, 1: 1, 2: 0 })
|
|
// }
|
|
// }, { immediate: true })
|
|
|
|
watch([_colorEnd, _colorStart], () => {
|
|
recolorShader();
|
|
});
|
|
|
|
onMounted(async () => {
|
|
recolorShader();
|
|
await initShader();
|
|
window.addEventListener("resize", resizeShader, true);
|
|
emit("ready");
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener("resize", resizeShader);
|
|
killShader();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<canvas
|
|
ref="canvas"
|
|
id="background"
|
|
:class="{ pixelated: settingsStore.shaderPixelated }"
|
|
width="480"
|
|
height="270"
|
|
>test</canvas
|
|
>
|
|
</template>
|
|
|
|
<style scoped>
|
|
#background {
|
|
left: 0;
|
|
position: absolute;
|
|
height: 100%;
|
|
width: 100%;
|
|
}
|
|
|
|
#background.pixelated {
|
|
image-rendering: pixelated;
|
|
}
|
|
</style>
|