fix: シェーダーの読み込みが完了してからレンダリングを行うように
This commit is contained in:
parent
afcc37d886
commit
e06f37a7d4
|
@ -20,6 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.container">
|
||||
<div :class="$style.preview">
|
||||
<canvas ref="canvasEl" :class="$style.previewCanvas"></canvas>
|
||||
<MkLoading v-if="canvasLoading" :class="$style.previewSpinner"/>
|
||||
<div :class="$style.previewContainer">
|
||||
<div class="_acrylic" :class="$style.previewTitle">{{ i18n.ts.preview }}</div>
|
||||
<div class="_acrylic" :class="$style.previewControls">
|
||||
|
@ -74,6 +75,8 @@ const emit = defineEmits<{
|
|||
|
||||
const dialog = useTemplateRef('dialog');
|
||||
|
||||
const canvasLoading = ref(false);
|
||||
|
||||
async function cancel() {
|
||||
if (layers.length > 0) {
|
||||
const { canceled } = await os.confirm({
|
||||
|
@ -91,7 +94,9 @@ const layers = reactive<ImageEffectorLayer[]>([]);
|
|||
|
||||
watch(layers, async () => {
|
||||
if (renderer != null) {
|
||||
renderer.setLayers(layers);
|
||||
canvasLoading.value = true;
|
||||
await renderer.setLayers(layers);
|
||||
canvasLoading.value = false;
|
||||
}
|
||||
}, { deep: true });
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.container">
|
||||
<div :class="$style.preview">
|
||||
<canvas ref="canvasEl" :class="$style.previewCanvas"></canvas>
|
||||
<MkLoading v-if="canvasLoading" :class="$style.previewSpinner"/>
|
||||
<div :class="$style.previewContainer">
|
||||
<div class="_acrylic" :class="$style.previewTitle">{{ i18n.ts.preview }}</div>
|
||||
<div v-if="props.image == null" class="_acrylic" :class="$style.previewControls">
|
||||
|
@ -89,6 +90,8 @@ import { genId } from '@/utility/id.js';
|
|||
|
||||
const $i = ensureSignin();
|
||||
|
||||
const canvasLoading = ref(true);
|
||||
|
||||
function createTextLayer(): WatermarkPreset['layers'][number] {
|
||||
return {
|
||||
id: genId(),
|
||||
|
@ -232,6 +235,13 @@ let imageBitmap: ImageBitmap | null = null;
|
|||
async function initRenderer() {
|
||||
if (canvasEl.value == null) return;
|
||||
|
||||
canvasLoading.value = true;
|
||||
|
||||
await Promise.all([
|
||||
sampleImage_3_2_loading,
|
||||
sampleImage_2_3_loading,
|
||||
]);
|
||||
|
||||
if (sampleImageType.value === '3_2') {
|
||||
renderer = new WatermarkRenderer({
|
||||
canvas: canvasEl.value,
|
||||
|
@ -270,7 +280,9 @@ async function initRenderer() {
|
|||
|
||||
await renderer!.setLayers(preset.layers);
|
||||
|
||||
renderer!.render();
|
||||
await renderer!.render();
|
||||
|
||||
canvasLoading.value = false;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
|
|
|
@ -196,40 +196,35 @@ export class ImageEffector<IEX extends ReadonlyArray<ImageEffectorFx<any, any, a
|
|||
return shaderProgram;
|
||||
}
|
||||
|
||||
private async getOrLoadShaderProgram(fx: ImageEffectorFx): Promise<WebGLProgram> {
|
||||
let shaderProgram = this.shaderCache.get(fx.id);
|
||||
if (shaderProgram) return shaderProgram;
|
||||
|
||||
let shaderSource: string;
|
||||
if (typeof fx.shader === 'string') {
|
||||
shaderSource = fx.shader;
|
||||
} else {
|
||||
shaderSource = await fx.shader();
|
||||
}
|
||||
shaderProgram = this.initShaderProgram(`#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`, shaderSource);
|
||||
this.shaderCache.set(fx.id, shaderProgram);
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
private async renderLayer(layer: ImageEffectorLayer, preTexture: WebGLTexture) {
|
||||
const gl = this.gl;
|
||||
|
||||
const fx = this.fxs.find(fx => fx.id === layer.fxId);
|
||||
if (fx == null) return;
|
||||
|
||||
const cachedShader = this.shaderCache.get(fx.id);
|
||||
let shaderProgram: WebGLProgram;
|
||||
|
||||
if (cachedShader != null) {
|
||||
shaderProgram = cachedShader;
|
||||
} else {
|
||||
let shaderSource: string;
|
||||
|
||||
if (typeof fx.shader === 'string') {
|
||||
shaderSource = fx.shader;
|
||||
} else {
|
||||
shaderSource = await fx.shader();
|
||||
}
|
||||
|
||||
shaderProgram = this.initShaderProgram(`#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`, shaderSource);
|
||||
}
|
||||
|
||||
if (cachedShader == null) {
|
||||
this.shaderCache.set(fx.id, shaderProgram);
|
||||
}
|
||||
const shaderProgram = await this.getOrLoadShaderProgram(fx);
|
||||
|
||||
gl.useProgram(shaderProgram);
|
||||
|
||||
|
@ -268,6 +263,13 @@ export class ImageEffector<IEX extends ReadonlyArray<ImageEffectorFx<any, any, a
|
|||
public async render() {
|
||||
const gl = this.gl;
|
||||
|
||||
// 全レイヤーのshaderロードを事前に完了させる
|
||||
await Promise.all(this.layers.map(async (layer) => {
|
||||
const fx = this.fxs.find(fx => fx.id === layer.fxId);
|
||||
if (!fx) return;
|
||||
await this.getOrLoadShaderProgram(fx);
|
||||
}));
|
||||
|
||||
{
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.originalImageTexture);
|
||||
|
@ -359,7 +361,7 @@ export class ImageEffector<IEX extends ReadonlyArray<ImageEffectorFx<any, any, a
|
|||
this.paramTextures.delete(k);
|
||||
}
|
||||
|
||||
this.render();
|
||||
await this.render();
|
||||
}
|
||||
|
||||
public changeResolution(width: number, height: number) {
|
||||
|
|
Loading…
Reference in New Issue