ArthurN
ArthurN

Reputation: 179

Adding background image to WebGL 3D scene

I wrote a code that tried to draw only the background image in a WebGL 3D scene. Here are the relevant parts of the code:

<script id="shader-fs" type="x-shader/x-fragment">
varying highp vec2 vTexCoord;

uniform sampler2D uSampler;

void main(void) {
    gl_FragColor = texture2D(uSampler, vec2(vTexCoord.s, vTexCoord.t));
}
</script>

<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

varying highp vec2 vTexCoord;

void main(void) {
    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
    vTexCoord = aTextureCoord;
}
</script>

<script>
var VBack = [
    -24.0,  0.0, 0.0,
     24.0,  0.0, 0.0,
     24.0, 48.0, 0.0,
    -24.0, 48.0, 0.0
    ];

var vTBack = [
    0.0, 0.0,
    1.0, 0.0,
    1.0, 1.0,
    0.0, 1.0
    ];

var VBuffer;
var vTBuffer;

function initMatrix() {
    orthoMatrix = makeOrtho(-24.0, 24.0, 0.0, 48.0, 20.0, -20.0);    // From glUtils.js
    mvMatrix = Matrix.I(4);
    ...
}   

function handleBkTex(tex) {
    GL.bindTexture(GL.TEXTURE_2D, tex);
    GL.pixelStorei(GL.UNPACK_FLIP_Y_WEBGL, true);
    GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, tex.Img);
    GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
    GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
    GL.bindTexture(GL.TEXTURE_2D, null);
}

function initBkgnd() {
    backTex = GL.createTexture();
    backTex.Img = new Image();
    backTex.Img.onload = function() {
        handleBkTex(backTex);
    }
    backTex.Img.src = "Bkgnd.jpg";
}

function drawBkgnd() {
    GL.bindBuffer(GL.ARRAY_BUFFER, VBuffer);
    GL.vertexAttribPointer(vertexPositionAttribute, 3, GL.FLOAT, false, 0, 0);

    GL.bindBuffer(GL.ARRAY_BUFFER, vTBuffer);
    GL.vertexAttribPointer(texCoordAttribute, 2, GL.FLOAT, false, 0, 0);

    GL.activeTexture(GL.TEXTURE0);
    GL.bindTexture(GL.TEXTURE_2D, backTex);
    GL.uniform1i(GL.getUniformLocation(shaderProgram, "uSampler"), 0);

    GL.drawArrays(GL.TRIANGLE_STRIP, 0, 4);
}


function start() {
    var canvas = document.getElementById("glcanvas");
    initWebGL(canvas);

    if (GL) {
        initShaders();
        initBuffers();
        initMatrix();
        initBkgnd();
        drawBkgnd();
    }
}

The canvas size is 512 x 512, the same as the image size. But I don't get the correct image on the canvas. How to do this correctly?

Upvotes: 1

Views: 3867

Answers (2)

ArthurN
ArthurN

Reputation: 179

I found some small errors in my code. Here are they:

  • WebGL scene must always be redrawn. So the function drawBkgnd() must be called repeatedly, using setInterval() or requestAnimationFrame().
  • To use drawArrays() with GL_TRIANGLE_STRIP to draw a rectangle correctly, the order of the vertices must be:

    *2        *3
    
    
    *0        *1
    

    or any equivalent order, but not:

    *3        *2
    
    
    *0        *1
    

    So the order of the vertices in VBack must be changed to:

    var VBack = [
        -24.0,  0.0, 0.0,
         24.0,  0.0, 0.0,
        -24.0, 48.0, 0.0
         24.0, 48.0, 0.0,
    ];
    

    and the order of vertices in vTBack must also be changed accordingly.

Upvotes: 1

user128511
user128511

Reputation:

Do you want the answer to be how to setup a 3D matrix to draw a 2D image or do you want the answer to be how to do this efficiently?

Here's the efficient answer. There's no reason to use 3D to draw 2D. Change your vertices to

var VBack = [
  -1, -1,
   1, -1,
   1,  1,
  -1,  1,
];

Change your call to vertexAttribPointer to

GL.vertexAttribPointer(vertexPositionAttribute, 2, GL.FLOAT, false, 0, 0);

Change your vertex shader to

attribute vec4 aVertexPosition;
attribute vec2 aTextureCoord;

varying highp vec2 vTexCoord;

void main(void) {
    gl_Position = aVertexPosition;
    vTexCoord = aTextureCoord;
}

And it should work.

See this set of articles for more about 2D in WebGL for more.

Upvotes: 2

Related Questions