Drawing multiple 2D images in WebGL

你。 提交于 2019-12-05 11:54:38
Cutch

The following code does the following:

  1. Compiles the vertex and fragment shaders
  2. Links them together into a shader program
  3. Creates a vertex buffer to hold texture coordinates and fills it (texCoordBuffer)
  4. Creates a texture (createTexture)
  5. Configures how the texture is sampled (texParameteri)

The above 5 steps only need to be run once.

    vertexShader = createShaderFromScriptElement(contextGL, "2d-vertex-shader");
    fragmentShader = createShaderFromScriptElement(contextGL, "2d-fragment-shader");

    program = createProgram(contextGL, [vertexShader, fragmentShader]);
    contextGL.useProgram(program);

    var positionLocation = contextGL.getAttribLocation(program, "a_position");

    var texCoordLocation = contextGL.getAttribLocation(program, "a_texCoord");

    var texCoordBuffer = contextGL.createBuffer();
    contextGL.bindBuffer(contextGL.ARRAY_BUFFER, texCoordBuffer);

    contextGL.enableVertexAttribArray(texCoordLocation);
    contextGL.vertexAttribPointer(texCoordLocation, 2, contextGL.FLOAT, false, 0, 0);

    var texture = contextGL.createTexture();
    contextGL.bindTexture(contextGL.TEXTURE_2D, texture);

    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_WRAP_S, contextGL.CLAMP_TO_EDGE);
    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_WRAP_T, contextGL.CLAMP_TO_EDGE);
    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_MIN_FILTER, contextGL.NEAREST);
    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_MAG_FILTER, contextGL.NEAREST);

    setRectangle(contextGL, 0.0, 0.0, 1.0, 1.0);

The rest of the code must execute for each image you want to draw and it does the following:

  1. Uploads the image into the texture (texImage2D)
  2. Creates a vertex buffer to hold positions and fills it (buffer)
  3. Calls drawArrays
    contextGL.texImage2D(contextGL.TEXTURE_2D, 0, contextGL.RGBA, contextGL.RGBA,contextGL.UNSIGNED_BYTE, imageObjectArray[0].displayObject.data);

    var resolutionLocation = contextGL.getUniformLocation(program, "u_resolution");
    contextGL.uniform2f(resolutionLocation, canvas.width, canvas.height);

    var buffer = contextGL.createBuffer();
    contextGL.bindBuffer(contextGL.ARRAY_BUFFER, buffer);
    contextGL.enableVertexAttribArray(positionLocation);
    contextGL.vertexAttribPointer(positionLocation, 2, contextGL.FLOAT, false, 0, 0);

    setRectangle(contextGL, imageObjectArray[0].x, imageObjectArray[0].y, imageObjectArray[0].width, imageObjectArray[0].height);

    // draw
    contextGL.drawArrays(contextGL.TRIANGLES, 0, 6);

You need to split step 2 into separate steps. The first step, creating the vertex buffer for posistions, should only be executed once. The second step, filling the position of the image, needs to be executed for each image you want to draw.

I should say that my suggestions will not give the optimal implementation but it will get you drawing more than 1 image. To be optimal you should consider doing:

  • Implement texture atlasing (pack all your images onto a single texture).
  • Only upload your texture and position coordinates once.
  • Use a better vertex and fragment shader to pick which image is being drawn (texture coordinate offset), where it is being drawn (position offset) and how large it should be (width & height scaling)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!