2016-05-03 13 views
0

Ich arbeite an einem Projekt, wo ich einen Webcam-Stream auf eine sphärische Geometrie einbinden. Da ich neu bei Shadern bin und lernen möchte, wie das funktioniert, möchte ich die Webcam mit einer relativ normalen Größe auf ein statisches Hintergrundbild in die Kugel projizieren.WebGL Textur über Textur

Also muss das Webcam-Video nur einen kleinen Teil der Kugel abdecken, aber das Hintergrundbild muss die gesamte Kugel abdecken.

Derzeit sieht meine Webcam-Bild wie folgt aus: current situation

Aber ich will es so aussehen: desired situation

Ich habe folgende 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); 
     } 

und die folgenden Fragment-Shader, der derzeit "Video" zeichnet, welches der Webcam-Stream ist.

 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; 
     } 

Und meine Render-Funktion wie folgt aufgebaut ist:

haben
this.program.use(); 

    //setup attributes 
    //setup uniforms 
    context.gl.uniformMatrix4fv(this.program.uniform.projectionMat, false, projectionMat); 
    context.gl.uniformMatrix4fv(this.program.uniform.modelViewMat, false, modelViewMat); 

    context.gl.bindBuffer(context.gl.ARRAY_BUFFER, this.vertBuffer); 
    context.gl.bindBuffer(context.gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); 

    context.gl.enableVertexAttribArray(this.program.attrib.position); 
    context.gl.enableVertexAttribArray(this.program.attrib.texCoord); 
    context.gl.enableVertexAttribArray(this.program.attrib.texVideoCoord); 

    context.gl.vertexAttribPointer(this.program.attrib.position, 3, context.gl.FLOAT, false, 20, 0); 
    context.gl.vertexAttribPointer(this.program.attrib.texCoord, 2, context.gl.FLOAT, false, 20, 12); 
    context.gl.vertexAttribPointer(this.program.attrib.texVideoCoord, 2, context.gl.FLOAT, false, 20, 12); 

    var u_backgroundLocation = context.gl.getUniformLocation(this.program.program, "u_background"); 
    var u_videoLocation = context.gl.getUniformLocation(this.program.program, "u_video"); 
    context.gl.uniform1i(u_backgroundLocation, 0); 
    context.gl.uniform1i(u_videoLocation, 1); 

    //activetexture/bind 
    context.gl.activeTexture(context.gl.TEXTURE0); 
    context.gl.bindTexture(context.gl.TEXTURE_2D, self.textureBackground); 
    context.gl.texImage2D(context.gl.TEXTURE_2D, 0, context.gl.RGBA, context.gl.RGBA, context.gl.UNSIGNED_BYTE, self.canvasElement); 
    context.gl.activeTexture(context.gl.TEXTURE1); 
    context.gl.bindTexture(context.gl.TEXTURE_2D, self.textureVideo); 
    context.gl.texImage2D(context.gl.TEXTURE_2D, 0, context.gl.RGBA, context.gl.RGBA, context.gl.UNSIGNED_BYTE, self.videoElement); 

    //drawarrays/drawelements 
    context.gl.drawElements(context.gl.TRIANGLES, this.indexCount, context.gl.UNSIGNED_SHORT, 0); 

ich keine Ahnung, wie der Kugel weiterhin die Webcam erscheinen skaliert und Teil als über sie gespannt entgegen. Die Webcam ist eine 100-Grad-Kamera und sollte als solche in der Kugel positioniert werden.

Antwort

0

Wenn Sie Ihr UV über die Kugel haben, können Sie es ganz für die Hintergrundbildabtastung verwenden, und einen kleineren Teil davon zum Abtasten der Videotextur.

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; 
} 

EDIT:

Hier ist die Arbeits shadertoy: https://www.shadertoy.com/view/MsdSWs

+0

Große, funktioniert gut macht. Offensichtlich Textur (sollte Textur2D werden (aber das funktioniert super. Danke. – martijn

0

Eine andere Möglichkeit, es zu tun wäre, Ihr Video UV einstellen Koordinaten, so dass die 0 < -> 1 Bereich der Bereich, den Sie repräsentiert wollen sehen Sie das Video

Mit anderen Worten: der Hintergrund des UVs gehen

0,0  0.3 0.7 1.0 
    +------+------+------+ 
    |  |  |  | 
    |  |  |  | 
    |  |  |  | 
0.3 +------+------+------+ 
    |  |  |  | 
    |  |  |  | 
    |  |  |  | 
0.7 +------+------+------+ 
    |  |  |  | 
    |  |  |  | 
    |  |  |  | 
1.0 +------+------+------+ 

aber die Video-UVs gehen

-1,-1  0  1  2 
    +------+------+------+ 
    |  |  |  | 
    |  |  |  | 
    |  |  |  | 
    0 +------+------+------+ 
    |  |......|  | 
    |  |......|  | 
    |  |......|  | 
    1 +------+------+------+ 
    |  |  |  | 
    |  |  |  | 
    |  |  |  | 
    2 +------+------+------+ 

, die den ...... Teil den Teil zwischen 0 und 1

Dann wäre Sie Shader

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); 
     vec2 m = step(vec2(0), vTexVideoCoord) * step(vTexVideoCoord, vec2(1)); 
     gl_FragColor = mix(background, video, m.x * m.y); 
    }