我正在尝试使用Vue JS来显示一些非常简单的WebGL。我在我的canvas元素内使用Vue方法调用来启动呈现WebGL的功能。一切工作正常,除了渲染的图像在屏幕上闪烁一次然后消失。图像是一个简单的三角形,渲染后应该仅位于屏幕上。我找不到解决方案?
由于我是个新手,所以我可能犯了一些明显的错误,这就是问题所在,可能是我猜到了通过Vue将简单的基本WebGl合并到HTML中的标准化方法,但是我只是找不到它?
可能的解决方案是什么?不幸的是,我应该只使用基本的WebGL(而不是Three.js或其他任何东西),而是使用基本的Vue JS。
我将在下面解释细节。
我对Vue JS相当陌生,对WebGL也很陌生。我正在YouTube上的this系列教程中首次学习WebGL,其中链接的特定视频包含了我为解决此问题而编写的代码。
与vid唯一的,也许是与众不同的事情当然是使用Vue JS作为UI框架,而不是编写纯HTML和Javascript文件,然后手动使用node js来设置服务器。
在本教程中,他通过html中的标记链接了一个单独的包含WebGL代码的.js文件。在此脚本中,Javascript仅使用查询选择器来获取画布及其上下文,并将其分配为输出渲染的位置。
在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.
.
.
}
}
}
现在这实际上可以工作了,并且实际上已经渲染了红色的小三角形-除非将其渲染到屏幕上,否则它就会消失。
这是我想发生的事情:当vue组件第一次加载时,它将运行我放置在其中的runWebGL()方法,创建并在画布上显示lil红色三角形。但是,该方法完成后,它将不再运行,因此其中的所有内容都将被破坏,并且没有WebGL可以输出。
例如,如果我在runWebGL()的末尾放置了一个警报函数以防止该函数自动结束,则可以看到三角形一直输出到屏幕上,直到用户关闭警报为止。
那我假设的是,当这家伙在视频中做过的时候,您通过标记将一些脚本直接附加到html上,无论它们是本地还是外部引用的脚本,一旦完成,它们就不会关。因此,即使它们已经解析到最后,它们中的数据等仍然可用?
那我该如何在Vue JS中解决这个问题?我应该实现某种方法来使Vue JS方法“运行”,即使其中的代码已经执行完了吗?还是有其他更标准化的方法来对WebGL和Vue JS进行网格划分?
我知道那里有一些WebGL框架,并且有一些试图将Vue和WebGL融合在一起,但是不幸的是我不应该使用它们-我必须尽可能地接近它我可以使用原生VueJS和纯WebGL。
非常感谢您的帮助!
我在runWebGL()中放入的Javascript和WebGL代码与视频中的代码相同:
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);
答案 0 :(得分:1)
您需要详细了解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>
答案 1 :(得分:0)
stdon的答案非常适合使WebGL在首次加载Vue应用程序时自动启动并停留在该位置。谢谢!
尽管如此,我最终想要做的是让WebGL 不是自动启动,而是单击按钮即可打开。自动启动它应该是我开发的更简单的起点。
我自己进行了尝试,然后单击按钮时就激活了“ runWebGL”方法-从而无需将{{runWebGL()}}放在canvas标记内即可自动调用该方法-并且它起作用了!
但是stdon使用mount的答案是我最初要求的正确答案,应该得到支持。谢谢!
请注意,stdon回答中的代码可用于将WebGL设置为在加载Vue应用程序后自动运行。下面的是我使用的按钮设置。
HTML
<template>
<div id="app">
<button @click="runWebGL"> Start WebGL </button>
<canvas></canvas>
</div>
</template>
JavaScript
<script>
export default {
.
.
methods: {
runWebGL(){
//The Javascript & WebGL code from my original question
}
}
.
.
}
</script>