WebGL 在启动时不显示图像

问题描述 投票:0回答:1

我编写了一个 WebGL-React-App,当我导入文件时,它应该加载 4 个平面和 4 个图像。当我导入文件时,所有平面都是蓝色的,并且只有在移动视图时才会加载图像。我如何管理文件导入后立即加载图像?我读过几个类似的问题,这些问题都是用“Promise”解决的,但没有运气将其转移到我的代码中。

这是我的代码:

export function createLabel(gl, desc) {

console.log("create label: " + desc);

let coords = buildQuadricTriangleStrip(0.5);
let texture = null;

if (desc === DESC.N) {
    coords = translateQuad(coords, 0.5, -0.25, 0);
    texture = loadTexture(gl, "/images/n.png");
}

if (desc === DESC.S) {
    coords = rotateQuad(coords, ROT_AXIS.Z, 180);
    coords = translateQuad(coords, -0.5, 0.25, 0);
    texture = loadTexture(gl, "/images/s.png");
}

if (desc === DESC.E) {
    coords = rotateQuad(coords, ROT_AXIS.Z, 180);
    //coords = rotateQuad(coords, ROT_AXIS.Z, 180);
    coords = translateQuad(coords, 0.25, -0.5, 0);
    texture = loadTexture(gl, "/images/e.png");
}

if (desc === DESC.W) {
    coords = rotateQuad(coords, ROT_AXIS.Z, 180);
    coords = translateQuad(coords, 0.25, 1, 0);
    texture = loadTexture(gl, "/images/w.png");
}

//console.log(texture);

const textureCoordinates = [
    0, 1,
    1, 1,
    0, 0,
    1, 0
]

const indices = [
    2, 3, 1,
    0, 1, 2
]

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);

const textureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

let vs = document.getElementById("vshaderlabel").textContent;
let fs = document.getElementById("fshaderlabel").textContent;

const shaderProgram = shader.initShaderProgram(gl, vs, fs);

const programInfo = {
    program: shaderProgram,
    attribLocations: {
        vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"),
        textureCoord: gl.getAttribLocation(shaderProgram, 'aTextureCoord'),
    },
    uniformLocations: {
        projectionMatrix: gl.getUniformLocation(shaderProgram, "uProjectionMatrix"),
        modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"),
        uSampler: gl.getUniformLocation(shaderProgram, 'uSampler'),
    },
};

return {
    position: positionBuffer,
    textureCoord: textureCoordBuffer,
    indices: indexBuffer,
    positionSize: coords.length,
    texture,
    programInfo
};
}

 function loadTexture(gl, url) {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);

const level = 0;
const internalFormat = gl.RGBA;
const width = 1;
const height = 1;
const border = 0;
const srcFormat = gl.RGBA;
const srcType = gl.UNSIGNED_BYTE;
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue

gl.texImage2D(
    gl.TEXTURE_2D,
    level,
    internalFormat,
    width,
    height,
    border,
    srcFormat,
    srcType,
    pixel,
);

const image = new Image();

image.addEventListener('load', function () {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        srcFormat,
        srcType,
        image,
    );

    // WebGL1 has different requirements for power of 2 images
    // vs non power of 2 images so check if the image is a
    // power of 2 in both dimensions.
    if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
        // Yes, it's a power of 2. Generate mips.
        gl.generateMipmap(gl.TEXTURE_2D);
    } else {
        // No, it's not a power of 2. Turn off mips and set
        // wrapping to clamp to edge
        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);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    }
});
image.src = url;

return texture;
 }

 function isPowerOf2(value) {
return (value & (value - 1)) === 0;
 }

export function draw(gl, projectionMatrix, modelViewMatrix, buffers) {
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(buffers.programInfo.attribLocations.vertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(buffers.programInfo.attribLocations.vertexPosition);

gl.bindBuffer(gl.ARRAY_BUFFER, buffers.textureCoord);
gl.vertexAttribPointer(buffers.programInfo.attribLocations.textureCoord, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(buffers.programInfo.attribLocations.textureCoord);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);

gl.useProgram(buffers.programInfo.program);

gl.uniformMatrix4fv(
    buffers.programInfo.uniformLocations.projectionMatrix,
    false,
    projectionMatrix
);
gl.uniformMatrix4fv(
    buffers.programInfo.uniformLocations.modelViewMatrix,
    false,
    modelViewMatrix
);

gl.activeTexture(gl.TEXTURE0);
// Bind the texture to texture unit 0
gl.bindTexture(gl.TEXTURE_2D, buffers.texture);
// Tell the shader we bound the texture to texture unit 0
gl.uniform1i(buffers.programInfo.uniformLocations.uSampler, 0);

//gl.drawArrays(gl.TRIANGLE_STRIP, 0, buffers.positionSize / 3);
{
    const vertexCount = buffers.positionSize / 2;
    const type = gl.UNSIGNED_SHORT;
    const offset = 0;
    gl.drawElements(gl.TRIANGLES, vertexCount, type, offset);
}
}
javascript webgl
1个回答
0
投票
Finally i found my educated solution by using promise and async await:

Createlabel:

export async function createLabel(gl, desc) {

    console.log("create label: " + desc);

    let coords = buildQuadricTriangleStrip(0.5);
    let texture = null;

    if (desc === DESC.N) {
        coords = translateQuad(coords, 0.5, -0.25, 0);
        texture = await loadTexture(gl, "/images/n.png");
    }

    if (desc === DESC.S) {
        coords = rotateQuad(coords, ROT_AXIS.Z, 180);
        coords = translateQuad(coords, -0.5, 0.25, 0);
        texture = await loadTexture(gl, "/images/s.png");
    }

    if (desc === DESC.E) {
        coords = rotateQuad(coords, ROT_AXIS.Z, 180);
        //coords = rotateQuad(coords, ROT_AXIS.Z, 180);
        coords = translateQuad(coords, 0.25, -0.5, 0);
        texture = await loadTexture(gl, "/images/e.png");
    }

    if (desc === DESC.W) {
        coords = rotateQuad(coords, ROT_AXIS.Z, 180);
        coords = translateQuad(coords, 0.25, 1, 0);
        texture = await loadTexture(gl, "/images/w.png");
    }

    const textureCoordinates = [
        0, 1,
        1, 1,
        0, 0,
        1, 0
    ]

    const indices = [
        2, 3, 1,
        0, 1, 2
    ]

    const positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);

    const textureCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);

    const indexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

    let vs = document.getElementById("vshaderlabel").textContent;
    let fs = document.getElementById("fshaderlabel").textContent;

    const shaderProgram = shader.initShaderProgram(gl, vs, fs);

    const programInfo = {
        program: shaderProgram,
        attribLocations: {
            vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"),
            textureCoord: gl.getAttribLocation(shaderProgram, 'aTextureCoord'),
        },
        uniformLocations: {
            projectionMatrix: gl.getUniformLocation(shaderProgram, "uProjectionMatrix"),
            modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"),
            uSampler: gl.getUniformLocation(shaderProgram, 'uSampler'),
        },
    };

    return {
        position: positionBuffer,
        textureCoord: textureCoordBuffer,
        indices: indexBuffer,
        positionSize: coords.length,
        texture,
        programInfo
    };
}

Loadimage:

async function loadTexture(gl, url) {
    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);

    const level = 0;
    const internalFormat = gl.RGBA;
    const width = 1;
    const height = 1;
    const border = 0;
    const srcFormat = gl.RGBA;
    const srcType = gl.UNSIGNED_BYTE;
    const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue

    gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        width,
        height,
        border,
        srcFormat,
        srcType,
        pixel,
    );

    let image = await loadImage(url);

    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        srcFormat,
        srcType,
        image,
    );

    // WebGL1 has different requirements for power of 2 images
    // vs non power of 2 images so check if the image is a
    // power of 2 in both dimensions.
    if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
        // Yes, it's a power of 2. Generate mips.
        gl.generateMipmap(gl.TEXTURE_2D);
    } else {
        // No, it's not a power of 2. Turn off mips and set
        // wrapping to clamp to edge
        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);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    }

    return texture;
}

function loadImage(url) {
    return new Promise(resolve => {
        const image = new Image();
        image.addEventListener('load', () => {
            resolve(image);
        });
        image.src = url;
    });
}

Call in View3D:

 init = async(props) => {
    const canvas = document.querySelector("#glCanvas");
    const surr = document.querySelector("#draw");
    canvas.style.width = "100%";
    //canvas.style.height = "100%";
    canvas.width = surr.offsetWidth;

    const gl = canvas.getContext("webgl");
    if (!gl) {
      alert(
        "Unable to initialize WebGL. Your browser or machine may not support it."
      );
      return;
    }
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    if (props != null) {
      let p = plane.createPlane(gl, props, props.colors);

      let n = await tex.createLabel(gl, tex.DESC.N);
      let s = await tex.createLabel(gl, tex.DESC.S);
      let e = await tex.createLabel(gl, tex.DESC.E);
      let w = await tex.createLabel(gl, tex.DESC.W);

      let m = marker.createMarker(gl, props);

      let objects3d = {
        plane: p,
        n,
        s,
        e,
        w,
        m,
      };

      this.setState({ gl, objects3d });
      this.drawScene(gl, objects3d);
    }
  };
© www.soinside.com 2019 - 2024. All rights reserved.