martijn martijn - 1 year ago 81
Javascript Question

WebGL texture on top of texture

I'm working on a project where I incorporate a webcam stream onto a spherical geometry. As I'm new to shaders and want to learn how this works, I want to project the webcam into the sphere using a relatively normal size, on top of a static background image.

So the webcam video has to cover only a small portion of the sphere, but the background image has to cover the entire sphere.

Currently my webcam image looks like this:
current situation

But I want it to look like this:
desired situation

I have the following vertex shader:

uniform mat4 projectionMat;
uniform mat4 modelViewMat;
attribute vec3 position;
attribute vec2 texCoord;
attribute vec2 texVideoCoord;
varying vec2 vTexCoord;
varying vec2 vTexVideoCoord;

void main() {
vTexCoord = texCoord;
vTexVideoCoord = texVideoCoord;
gl_Position = projectionMat * modelViewMat * vec4( position, 1.0 );

And the following fragment shader, which currently draws "video" which is the webcam stream.

precision mediump float;

// Textures
uniform sampler2D u_background;
uniform sampler2D u_video;

varying vec2 vTexCoord;
varying vec2 vTexVideoCoord;

void main() {
vec4 background = texture2D(u_background, vTexCoord);
vec4 video = texture2D(u_video, vTexVideoCoord);
gl_FragColor = video;

And my render function is set up as followed:


//setup attributes
//setup uniforms, false, projectionMat);, false, modelViewMat);, this.vertBuffer);, this.indexBuffer);;;;, 3,, false, 20, 0);, 2,, false, 20, 12);, 2,, false, 20, 12);

var u_backgroundLocation =, "u_background");
var u_videoLocation =, "u_video");, 0);, 1);

//activetexture/bind;, self.textureBackground);, 0,,,, self.canvasElement);;, self.textureVideo);, 0,,,, self.videoElement);

//drawarrays/drawelements, this.indexCount,, 0);

I have no clue as how to continue to make the webcam appear scaled and part of the sphere as opposed to stretched over it. The webcam is a 100 degree camera, and should be positioned as such inside the sphere.

Answer Source

If you have your UV across the sphere, you could use it whole for the background image sampling, and smaller part of it for sampling the video texture.

vec2 vid_uv_start = vec2(0.2, 0.3);
vec2 vid_uv_end = vec2(0.6, 0.7);

uniform sampler2D u_background;
uniform sampler2D u_video;

varying vec2 vTexCoord;

void main()
    vec4 col = texture(u_background, vTexCoord);
    if((vTexCoord.x>=vid_uv_start.x && vTexCoord.x<=vid_uv_end.x)
        && (vTexCoord.y>=vid_uv_start.y && vTexCoord.y<=vid_uv_end.y))
        vec2 adjustedUV = (vTexCoord-vid_uv_start)/(vid_uv_end-vid_uv_start);
        col = texture(u_video, adjustedUV);
    gl_FragColor = col;


Here's the working shadertoy: