javascript - Vue JS - 如何让 WebGL 通过 Vue 渲染而不消失?

标签 javascript vue.js vuejs2 webgl webgl2

问题

我正在尝试使用 Vue JS 来显示一些非常简单的 WebGL。我在 canvas 元素内使用 Vue 方法调用来启动渲染 WebGL 的函数。一切正常,只是渲染的图像在屏幕上一闪而过,然后消失。该图像是一个简单的三 Angular 形,渲染后应该就位于屏幕上。我找不到解决办法吗?

由于我很新手,我可能犯了一些明显的错误,这就是问题所在,我可能猜测一些标准化的方法可以通过 Vue 将简单、基本的 WebGl 合并到 HTML 中,但我只是没找到?

有哪些可能的解决方案?不幸的是,我应该只使用基本的 WebGL(不是 Three.js 或其他任何东西),而是通过基本的 Vue JS。

我将在下面解释详细信息。

背景


我对 Vue JS 相当陌生,对 WebGL 也很陌生。我正在关注this YouTube 上的系列教程是我对 WebGL 的首次介绍,其中链接的特定视频包含我针对此问题所遵循的代码。

与我所做的视频唯一的(也许是显着的)不同之处当然是使用 Vue JS 作为 UI 框架,而不是编写纯 HTML 和 Javascript 文件,然后手动使用 Node js 来设置服务器。

在本教程中,他通过 html 中的标签链接了一个包含 WebGL 代码的单独 .js 文件。在此脚本中,Javascript 仅使用查询选择器来获取 Canvas 及其上下文,并将其指定为输出渲染的位置。

在 Vue JS 中,我不确定如何告诉 Vue 仅运行不是方法或计算等的外部脚本,因此我将 WebGL 代码放入方法中,并通过调用将其输出到屏幕vue模板中canvas标签内的方法:

<template>
<div id="app">

<canvas> {{runWebGL()}} </canvas>

</div>
</template>
export default{

methods: {

 runWebGL(){
   . 
   .
   //All the WebGLCode from the video - which for brevity I've pasted right at the bottom.
   .
   .
 }

}

}

现在这实际上起作用了,并且小红色三 Angular 形实际上被渲染了 - 除了它一旦渲染到屏幕上,它就消失了。


我对为什么的想法

我认为会发生这样的情况:当 vue 组件首次加载时,它会运行我放在那里的 runWebGL() 方法,创建并在 Canvas 中显示小红色三 Angular 形。然而,当该方法完成后,它不再运行,因此其中的所有内容都被破坏,并且没有 WebGL 可以输出。

如果我在 runWebGL() 末尾放置一个警报函数以防止该函数自动结束,您可以看到三 Angular 形一直输出到屏幕,直到用户关闭警报。

我假设的是,正如视频中那个人所做的那样,您通过标签将一些脚本直接附加到 html,无论是本地脚本还是外部引用脚本,一旦完成,它们就不会关闭。那么即使它们已经被解析到最后,其中的数据等仍然可用?

那么我该如何在 Vue JS 中解决这个问题呢?我是否应该实现某种方法来保持 Vue JS 方法“运行”,即使其中的代码已经执行完毕?或者是否有其他更标准化的方法来网格化 WebGL 和 Vue JS?

我知道有一些 WebGL 框架,并且有一些尝试混合 Vue 和 WebGL,但不幸的是我不应该使用它们 - 我必须让它尽可能接近尽可能使用原生 VueJS 和普通 WebGL。

非常感谢您的帮助!


Javascript 和 WebGL 代码与视频中的代码相同,我将其放入 runWebGL() 中:

const canvas = document.querySelector(`canvas`); 
const gl = canvas.getContext(`webgl`); 
if (!gl) { throw new Error(`webGL not supported`); } 
/* ***OUTLINE**** */ // load vertexData into Buffer // create vertex SharedArrayBuffer // create program // attach shaders to program // enable vertex attributes // draw 
console.log(`Starting...`); 
// create a triangle, x,y,z. WebGL uses OpenGL uses Float32 Arrays. // Typically don't use Float32 arrays in JS as per: // https://stackoverflow.com/questions/15823021/when-to-use-float32array-instead-of-array-in-javascript
// changing these points will alter where the corners of your triangle are. max is 1, min is -1 
const vertexData = new Float32Array([ 0, 1, 0, 1, -1, 0, -1, -1, 0, ]); const buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 
// bind this buffer as the current buffer; as an array of vertices 
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW); 
// STATIC_DRAW if not rewriting (optomise) common alternative is DYNAMIC_DRAW // Creates the vertex-shader; a mini program that runs on the GPU // this uses the GL shading language (not JS), hence the typed return for the function (ie 'void') // gl_position is the output of the shader; an array of 4 components from the buffer // vec3 indicates the three parts of x,y,z; this is converted to a vec4 by adding "1" to 'position' 
const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, ` attribute vec3 position; void main() { gl_Position = vec4(position, 1); } `); gl.compileShader(vertexShader); 
// create a fragment-shader // a fragment shader shades the pixels between vertices // the vec4 is in format RGB-A // try changing some of these numbers and see what happens // eg vec4(0,1,0,.5) gives a transparent green triangle 
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, ` void main(){ gl_FragColor = vec4(1, 0, 0, 1); } `); gl.compileShader(fragmentShader); 
// create a program that links the two shaders (vertex and fragment) // to the actual vertices 
const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); 
// load the attributes. // Currently we just have a single attribute `position` created with the vertex shader // Attributes are disabled by default - so we have to enable it 
const positionLocation = gl.getAttribLocation(program, `position`); gl.enableVertexAttribArray(positionLocation); 
// how webgl should retrieve data from the currently bound buffer // what is being retrieved? positionLocation // how many elements to read at a time? 3 (x,y,z) // what type are the elements? floating point numbers (from Float32Array) // remaining arguments are not used ('normalise' is an advanced optomisation, not needed here) 
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); 
// create an excutable program on the graphics card // drawArrays, 2nd argument is which vertex to start at, how many to draw? (in this case there are 3 vertices all with 3 attributes (x,y,z)) 
gl.useProgram(program); 


gl.drawArrays(gl.TRIANGLES, 0, 3);const canvas = document.querySelector(`canvas`); 
const gl = canvas.getContext(`webgl`); 
if (!gl) { throw new Error(`webGL not supported`); } 
/* ***OUTLINE**** */ // load vertexData into Buffer // create vertex SharedArrayBuffer // create program // attach shaders to program // enable vertex attributes // draw 
console.log(`Starting...`); 
// create a triangle, x,y,z. WebGL uses OpenGL uses Float32 Arrays. // Typically don't use Float32 arrays in JS as per: // https://stackoverflow.com/questions/15823021/when-to-use-float32array-instead-of-array-in-javascript
// changing these points will alter where the corners of your triangle are. max is 1, min is -1 
const vertexData = new Float32Array([ 0, 1, 0, 1, -1, 0, -1, -1, 0, ]); const buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 
// bind this buffer as the current buffer; as an array of vertices 
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW); 
// STATIC_DRAW if not rewriting (optomise) common alternative is DYNAMIC_DRAW // Creates the vertex-shader; a mini program that runs on the GPU // this uses the GL shading language (not JS), hence the typed return for the function (ie 'void') // gl_position is the output of the shader; an array of 4 components from the buffer // vec3 indicates the three parts of x,y,z; this is converted to a vec4 by adding "1" to 'position' 
const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, ` attribute vec3 position; void main() { gl_Position = vec4(position, 1); } `); gl.compileShader(vertexShader); 
// create a fragment-shader // a fragment shader shades the pixels between vertices // the vec4 is in format RGB-A // try changing some of these numbers and see what happens // eg vec4(0,1,0,.5) gives a transparent green triangle 
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, ` void main(){ gl_FragColor = vec4(1, 0, 0, 1); } `); gl.compileShader(fragmentShader); 
// create a program that links the two shaders (vertex and fragment) // to the actual vertices 
const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); 
// load the attributes. // Currently we just have a single attribute `position` created with the vertex shader // Attributes are disabled by default - so we have to enable it 
const positionLocation = gl.getAttribLocation(program, `position`); gl.enableVertexAttribArray(positionLocation); 
// how webgl should retrieve data from the currently bound buffer // what is being retrieved? positionLocation // how many elements to read at a time? 3 (x,y,z) // what type are the elements? floating point numbers (from Float32Array) // remaining arguments are not used ('normalise' is an advanced optomisation, not needed here) 
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); 
// create an excutable program on the graphics card // drawArrays, 2nd argument is which vertex to start at, how many to draw? (in this case there are 3 vertices all with 3 attributes (x,y,z)) 
gl.useProgram(program); 


gl.drawArrays(gl.TRIANGLES, 0, 3);

最佳答案

您需要了解更多关于the life cycle of the vue-instance的信息。例如尝试 the mounted hook :

<template>
<div id="app">
  <canvas></canvas>
</div>
</template>

<script>
export default{
  ...
  mounted () {
    this.runWebGL()
  },
  methods: {
    runWebGL(){
      ...
    }
  }
}
</script>
 

[ https://jsfiddle.net/stdob__/fyojs1vn/]

关于javascript - Vue JS - 如何让 WebGL 通过 Vue 渲染而不消失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55385538/

相关文章:

javascript - Node + MongoDB 问题 EADDRINUSE

vue.js - VueJS : Using A Loading Icon When Waiting For Results Of Asynchronous Database Calls

vue.js - 对于使用 Vue cli3 库的 Vuejs cli3 SPA 应用程序,SSR 构建表示 "document is not defined"

javascript - 如何重新加载html标签对象数据?

javascript - 如何在移动设备上从我的手机获取 console.log 输出?

javascript - 有没有办法在 Javascript 中正确地乘以两个 32 位整数?

javascript - 为什么当我选择第二个输入框时音译不起作用?

javascript - 如何使用 Vue js 显示 Cockpit CMS JSON 数据

vuejs2 - 如何在 Vue.js 组件中使用矩库

当图表数据被替换、更新等时,vue.js vue-chartjs 图表不更新