3
votes

I am struggeling with when and how to use activeTexture, bindtexture and gl.uniform1i('TextureLocation', 'texture'), Int) functions.

However, all of my stuff worked so far but it seems my rudimentary understanding starts to become a problem now.

I am trying to use a cubemap and a texture map in one shader. To test I am currently drawing two objects with this shader and try to color each with a different texture map. If I only use texturemap or cubemap the program runs nicely, so I assume both are loaded correctly. Now here is my boiled down fragment shader:

precision mediump float;
uniform int Switch; //switch between sphere and background
// normal
varying vec3 vNormal;
// texture
uniform mat4 TexMatrix;
uniform samplerCube texMap;

void main() {
        vec4 FragColor;

        //draw square
        if( Switch == 0 ) { 
            vec3 fTexCoord = vec4(vNormal,1.0)).xyz;
            FragColor = textureCube(texMap, fTexCoord);
        }

        //draw sphere
        else if( Switch == 1 ) { 
            // spherical coord -> kartesian coord
            float PI = 3.141592653;
            vec2 bTexCoord = vec2(2.0*atan((length(vec2(vNormal.x,vNormal.y)) - vNormal.x)/vNormal.y)/(2.0*PI),acos(vNormal.z)/PI);
            FragColor = texture2D(bumpMap, bTexCoord);
        }

        gl_FragColor = FragColor;
    }

this is where is where I initialize the two textures, the images are correctly loaded.

function initBumpMap(img){
    gl.Texture = gl.createTexture();
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, gl.Texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    //gl.generateMipmap(gl.TEXTURE_2D);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); // set the texture to repreat for values of (s,t) outside of [0,1] 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
    gl.uniform1i(gl.getUniformLocation(program, "bumpMap"), 0); //link texture to sampler
}

function initCubeMap(images){
    gl.CubeMap = gl.createTexture();
    gl.activeTexture(gl.TEXTURE1);
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, gl.CubeMap);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    //put images on cubemap
    gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z ,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE, images[0]);
    gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y ,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE, images[1]);
    gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE, images[2]);
    gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X ,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE, images[3]);
    gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X ,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE, images[4]);
    gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y ,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE, images[5]);

    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER,gl.NEAREST);
    gl.uniform1i(gl.getUniformLocation(program, "texMap"), 1); //link texture to sampler
}

and here is the main JavaScript/WebGL snippet

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, gl.Texture);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, gl.CubeMap); 
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    //draw square
    ...bind point and enable stuff for the square...        
    gl.uniform1i(gl.getUniformLocation(program,'Switch'),1); //switch to use bumpmap
    gl.bindTexture(gl.TEXTURE_2D, gl.Texture0);                 

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);


    // draw sphere
    ...bind point and enable stuff for the sphere...
    gl.uniform1i(gl.getUniformLocation(program,'Switch'),0); //switch to cube map
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, gl.CubeMap);

    for( var i=0; i < vertices.length; i+=3){
        gl.drawArrays(gl.TRIANGLES, i, 3);
    }

If I only use one if statement in the shader everything works find, the moment I try to use both textures nothing happens! Whats going on?

1

1 Answers

2
votes

Apperently I need to always set

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, gl.Texture);
    gl.uniform1i(gl.getUniformLocation(program, "bumpMap"), 0);
    gl.activeTexture(gl.TEXTURE1);
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, gl.CubeMap);
    gl.uniform1i(gl.getUniformLocation(program, "texMap"), 1);

before drawing, then it works! :D

EDIT: but why? what do I really need to set? why do I need to use all three commands?