收藏
回答

开启高性能 webgl渲染图片黑屏

框架类型 问题类型 操作系统 操作系统版本 手机型号 微信版本
小游戏 Bug iOS iOS 14.3 iPhone 12 pro 8.0.34

场景:在做的微信小游戏【首帧使用webgl渲染一张背景图】优化启动速度,子包的游戏包加载完成后自动运行【游戏场景】

问题:下面的渲染代码

1.【普通模式】iOSHighPerformance:false - webgl渲染bg.png【正常】 - 子包加载完成后【游戏场景渲染正常】

2.【高性能模式】iOSHighPerformance:true - webgl渲染bg.png【黑屏】 - 子包加载完成后【游戏场景渲染正常】 - 无相关报错日志

PS:高性能模式 - 无报错日志,俺对webgl不太懂,希望有人帮俺看看,谢谢啦

渲染代码:

// vertex shader
let VERTEX_SHADER_SOURCE =`
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {
    gl_Position = a_Position;  
    v_TexCoord = a_TexCoord;
}`;

// fragment shader
let FRAGMENT_SHADER_SOURCE =`
precision mediump float;
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main() {
    gl_FragColor = texture2D(u_Sampler, v_TexCoord);
}`;

let CANVAS_WIDTH;
let CANVAS_HEIGHT;
function drawImg(imgPath) {
    let canvas = wx.createCanvas(); //获取绘制二维上下文
    let gl = canvas.getContext('webgl',{stencil:true});
    if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
    }
    CANVAS_WIDTH = canvas.width;
    CANVAS_HEIGHT = canvas.height;
    gl.viewport(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    // Initialize shaders
    if (!initShaders(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)) {
        console.log('Failed to intialize shaders.');
        return;
    }
    // Specify the color for clearing <canvas>
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    GameGlobal.dycc = canvas;
    GameGlobal.screencanvas = GameGlobal.dycc || new _Canvas2.default();
    // Set texture
    if (!initTextures(gl, 4, imgPath)) {
        console.log('Failed to intialize the texture.');
        return;
    }
}


function initShaders(gl, vshader, fshader) {
    let program = createProgram(gl, vshader, fshader);
    if (!program) {
        console.log('Failed to create program');
        return false;
    }
    gl.useProgram(program);
    gl.program = program;
    return true;
}


function createProgram(gl, vshader, fshader) {
    // Create shader object
    let vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
    let fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
    if (!vertexShader || !fragmentShader) {
        return null;
    }
    // create a program object
    let program = gl.createProgram();
    if (!program) {
        console.log('gl.createProgram failed');
        return null;
    }
    // attach  the shader objects
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    // link the program object
    gl.linkProgram(program);
    // Check the result of linking
    let linked = gl.getProgramParameter(program, gl.LINK_STATUS);
    if (!linked) {
        let error = gl.getProgramInfoLog(program);
        console.log('Failed to link program: ' + error);
        gl.deleteProgram(program);
        gl.deleteShader(fragmentShader);
        gl.deleteShader(vertexShader);
        return null;
    }
    return program;
}


function loadShader(gl, type, source) {
    // create shader object
    let shader = gl.createShader(type);
    if (shader == null) {
        console.log('unable to create shader');
        return null;
    }
    // set shader source code
    gl.shaderSource(shader, source);
    // compile the shader
    gl.compileShader(shader);
    // check compile status
    let compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (!compiled) {
        let error = gl.getShaderInfoLog(shader);
        console.log('Failed to compile shader: ' + error);
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}


function initVertexBuffers(gl) {
    let imgWidth = 1;
    let imgHeight = 1960;
    let scaleX = imgWidth / imgWidth;
    let scaleY = CANVAS_WIDTH / imgWidth * imgHeight / CANVAS_HEIGHT;
    let verticesTexCoords0 = new Float32Array([
        -1.0, +1.0, 0.0, 1.0, // 前 2 位是位置坐标, 后 2 位是纹理坐标
        -1.0, -1.0, 0.0, 0.0,
        +1.0, +1.0, 1.0, 1.0,
        +1.0, -1.0, 1.0, 0.0
    ]);
    let verticesTexCoords = new Float32Array([
        // x y u v
        -scaleX, +scaleY, 0.0, 1.0,
        -scaleX, -scaleY, 0.0, 0.0,
        +scaleX, +scaleY, 1.0, 1.0,
        +scaleX, -scaleY, 1.0, 0.0
    ]);
    let n = 4; // The number of vertices
    let vertexTexCoordBuffer = gl.createBuffer();
    if (!vertexTexCoordBuffer) {
        console.log('Failed to create buffer object');
        return -1;
    }
    // Bind the buffer object to target
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
    let FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
    //Get the storage location of a_Position, assign and enable buffer
    let a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    if (a_Position < 0) {
        console.log('Failed to get the storage location of a_Position');
        return -1;
    }
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0);
    // Enable the assignment of the buffer object
    gl.enableVertexAttribArray(a_Position);
    // Get the storage location of a_TexCoord
    let a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
    if (a_TexCoord < 0) {
        console.log('Failed to get the storage location of a_TexCoord');
        return -1;
    }
    gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
    // Enable the assignment of the buffer object
    gl.enableVertexAttribArray(a_TexCoord);
    return n;
}


function initTextures(gl, n, imgPath) {
    let texture = gl.createTexture(); // Create a texture object
    if (!texture) {
        console.log('Failed to create the texture object');
        return false;
    }
    // Get the storage location of u_Sampler
    let u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
    if (!u_Sampler) {
        console.log('Failed to get the storage location of u_Sampler');
        return false;
    }
    let image = wx.createImage(); // Create the image object
    if (!image) {
        console.log('Failed to create the image object');
        return false;
    }
    // Register the event handler to be called on loading an image
    image.onload = function () {
        initVertexBuffers(gl);
        loadTexture(gl, texture, image);
        drawTexture(gl, n, u_Sampler);
    };
    // Tell the browser to load an image
    image.src = imgPath;
    return true;
}


function loadTexture(gl, texture, image) {
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // Flip the image's y axis
    // Enable texture unit0
    gl.activeTexture(gl.TEXTURE0);
    // Bind the texture object to the target
    gl.bindTexture(gl.TEXTURE_2D, texture);
    // Set the texture parameters(出现2 power的bug)
    // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    // Set the texture image
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
}


function drawTexture(gl, n, u_Sampler) {
    // Set the texture unit 0 to the sampler
    gl.uniform1i(u_Sampler, 0);
    // Clear <canvas>
    gl.clear(gl.COLOR_BUFFER_BIT);
    // Draw the rectangle
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
}
drawImg("bg.png")
回答关注问题邀请回答
收藏

1 个回答

  • 神奇的姜
    神奇的姜
    2023-03-30

    感谢官方大佬指点!问题解决!

    ...
    function drawImg(imgPath) {
        let canvas = wx.createCanvas(); //获取绘制二维上下文
        // 初始化canvas后首先手动设置canvas宽高,可解决本贴问题
        canvas.width = 375;
        canvas.height = 812;
    ...
    
    2023-03-30
    有用 1
    回复
登录 后发表内容