gpt4 book ai didi

javascript - 微信(WebGL)小游戏不能在设备上运行,但可以在 devtool 中运行

转载 作者:行者123 更新时间:2023-11-30 19:54:50 31 4
gpt4 key购买 nike

我想做什么

我正在尝试将我自己的基于 WebGL 的引擎移植到微信小游戏环境,目前只是尝试让 WebGL 上下文被粉红色清除:

WeChat Developer Tool - WebGL works

有什么问题

我已经按照腾讯提供的示例以及 ThreeJS 示例来设置游戏项目。它在微信开发者工具中运行良好(如上图所示),但是当我尝试在我的设备(Android 手机)上打开它时,它卡在 100% 加载屏幕:

Stuck in loading minigame

这样持续约1分钟,然后黑屏。

我的代码

我的代码中没有资源加载。这是我的 main.js 中的内容:


var ctx = canvas.getContext('webgl', {
antialias: true,
depth: true,
preserveDrawingBuffer: true
});

ctx.viewport(0,0,ctx.canvas.width,ctx.canvas.height)
ctx.colorMask(true,true,true,true)
ctx.depthMask(true)
ctx.enable(ctx.BLEND)
ctx.blendFunc(ctx.SRC_ALPHA, ctx.ONE_MINUS_SRC_ALPHA)
ctx.clearColor(1.0,0.0,1.0,1.0)

export default class Main {

constructor() {
window.requestAnimationFrame(this.loop.bind(this), canvas)
}

render() {
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT)
}

update() {

}

loop() {
this.update()
this.render()
window.requestAnimationFrame(this.loop.bind(this), canvas)
}
}

我的 game.js 也很简单:

import './weapp-adapter/index.js'
import './symbol'
import Main from './js/main'
new Main()

我的 game.json 只包含以下内容:

{
"deviceOrientation": "portrait"
}

附加信息

我还注意到,当我尝试 Threejs 示例(可在设备上运行)和渲染函数中的注释行时,它会表现相同(卡在 100% 加载中)。

最佳答案

解决方案

我终于想出了解决办法:

当我将 WebGL 上下文初始化放在动画帧的第一个调用中,而实际渲染在所有其他调用中完成时,它在我的 Android 设备上按预期工作。这是我更改过的 main.js:

export default class Main {

constructor() {
this.render = this.render_first
requestAnimationFrame(() => this.animate())
}

showmsg(t,c) {
wx.showModal({
title: ""+t,
content: ""+c,
showCancel: false,
confirmText:'OK',
success: function(res){}
});
}

animate() {
this.render();
requestAnimationFrame(() => this.animate())
}

render_first() {

this.render = this.render_normal
var _this = this
this.domElement = canvas

var contextAttributes = {
alpha: false,
depth: true,
stencil: false,
antialias: false
}

this.domElement.addEventListener("webglcontextlost", function(e){
_this.showmsg("WebGL","Context lost");
}, false)

this.domElement.addEventListener("webglcontextrestored", function(e){
_this.showmsg("WebGL","Context restored");
}, false)

this._gl = this.domElement.getContext( 'webgl', contextAttributes ) || this.domElement.getContext( 'experimental-webgl', contextAttributes )

var _gl = this._gl

var vsrc = ""
vsrc += "uniform mat4 uModelView;"
vsrc += "uniform mat4 uProjView;"
vsrc += "attribute highp vec4 aPosition;"
vsrc += "void main(void) {"
vsrc += " gl_Position = ( uProjView * uModelView ) * aPosition;"
vsrc += "}"

var vid = _gl.createShader(_gl.VERTEX_SHADER)
_gl.shaderSource(vid,vsrc)
_gl.compileShader(vid)
if (!_gl.getShaderParameter(vid, _gl.COMPILE_STATUS)) {
console.error("Vertex shader failed: ", _gl.getShaderInfoLog(vid))
}

this._vid = vid

var fsrc = ""
fsrc += "void main(void) {"
fsrc += " gl_FragColor = vec4(1.0,1.0,0.0,1.0);"
fsrc += "}"

var fid = _gl.createShader(_gl.FRAGMENT_SHADER)
_gl.shaderSource(fid,fsrc)
_gl.compileShader(fid)
if (!_gl.getShaderParameter(fid, _gl.COMPILE_STATUS)) {
console.error("Fragment shader failed: ", _gl.getShaderInfoLog(fid))
}

this._fid = fid

var pid = _gl.createProgram()
_gl.attachShader(pid,vid)
_gl.attachShader(pid,fid)
_gl.linkProgram(pid)

if (!_gl.getProgramParameter(pid, _gl.LINK_STATUS)) {
let info = _gl.getProgramInfoLog(pid)
console.error("Program link failed:", info )
}

_gl.useProgram(pid)

this._pid = pid

var aPosition = _gl.getAttribLocation(pid,"aPosition")
var uModelView = _gl.getUniformLocation(pid,"uModelView")
var uProjView = _gl.getUniformLocation(pid,"uProjView")

_gl.uniformMatrix4fv( uModelView, false, [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] )
_gl.uniformMatrix4fv( uProjView, false, [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] )

this.uni = [uModelView, uProjView]

this.phase = 0.0

var data = [0,0,0,1,0,0,0,1,0]
var idata = [0,1,2]

var vbID = _gl.createBuffer()
_gl.bindBuffer(_gl.ARRAY_BUFFER,vbID)
_gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(data), _gl.STATIC_DRAW)

var vbiID = _gl.createBuffer();
_gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, vbiID)
_gl.bufferData(_gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(idata), _gl.STATIC_DRAW)

_gl.vertexAttribPointer( aPosition, 3, _gl.FLOAT, false, 0, 0 )
_gl.enableVertexAttribArray( aPosition )
_gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, vbiID)

this.vb = [vbID,vbiID]

_gl.clearColor(1.0,0.0,1.0,1.0)
}

render_normal() {

var _gl = this._gl

var et = 60.0 / 1000.0
this.phase += 180.0 * 60.0 / 1000.0
var py = Math.sin(this.phase * Math.PI/180.0) * 0.5
_gl.uniformMatrix4fv( this.uni[0], false, [1,0,0,0,0,1,0,0,0,0,1,0,py,0,0,1] )

_gl.clear( _gl.COLOR_BUFFER_BIT )
_gl.drawElements(_gl.TRIANGLES, 3, _gl.UNSIGNED_SHORT, 0)

}
}

问题是什么

在实际设备上,微信小游戏似乎在一个单独的线程中运行动画循环,而不是主 JavaScript 执行。由于 WebGL (OpenGL) 上下文只能在同一个线程中访问(除了在多个线程可以共享相同上下文的 native 应用程序中),它会在设备上崩溃,因为渲染函数会尝试访问在不同线程中初始化的 gl 上下文。

这在微信开发者工具中是不可见的,因为该工具不能准确模拟设备架构的工作方式,并且动画帧和 JavaScript 执行似乎发生在同一个线程中。

关于javascript - 微信(WebGL)小游戏不能在设备上运行,但可以在 devtool 中运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54107987/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com