纹理之上的 WebGL 纹理
WebGL texture on top of texture
我正在开展一个项目,将网络摄像头流整合到球形几何体中。由于我是着色器的新手并且想了解它是如何工作的,所以我想使用相对正常的尺寸将网络摄像头投影到球体中,在静态背景图像之上。
因此网络摄像头视频只需覆盖球体的一小部分,但背景图像必须覆盖整个球体。
目前我的网络摄像头图像如下所示:
current situation
但我希望它看起来像这样:
desired situation
我有以下顶点着色器:
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 );
}
以及当前绘制 "video" 网络摄像头流的以下片段着色器。
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;
}
我的渲染函数设置如下:
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);
我不知道如何继续使网络摄像头显示为缩放比例和球体的一部分,而不是在其上拉伸。网络摄像头是一个 100 度的摄像头,应该放在球体内。
如果你的 UV 横跨整个球体,你可以将它整个用于背景图像采样,而将它的一小部分用于视频纹理采样。
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;
}
编辑:
这是可用的 shadertoy:https://www.shadertoy.com/view/MsdSWs
另一种方法是设置您的视频 UV 坐标,使 0<->1 范围代表您想要观看视频的区域
换句话说,背景的 UV 消失了
0,0 0.3 0.7 1.0
+------+------+------+
| | | |
| | | |
| | | |
0.3 +------+------+------+
| | | |
| | | |
| | | |
0.7 +------+------+------+
| | | |
| | | |
| | | |
1.0 +------+------+------+
但是视频 UV 消失了
-1,-1 0 1 2
+------+------+------+
| | | |
| | | |
| | | |
0 +------+------+------+
| |......| |
| |......| |
| |......| |
1 +------+------+------+
| | | |
| | | |
| | | |
2 +------+------+------+
这使得 ......
部分成为 0 和 1 之间的部分
那么你的着色器就是
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);
}
我正在开展一个项目,将网络摄像头流整合到球形几何体中。由于我是着色器的新手并且想了解它是如何工作的,所以我想使用相对正常的尺寸将网络摄像头投影到球体中,在静态背景图像之上。
因此网络摄像头视频只需覆盖球体的一小部分,但背景图像必须覆盖整个球体。
目前我的网络摄像头图像如下所示: current situation
但我希望它看起来像这样: desired situation
我有以下顶点着色器:
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 );
}
以及当前绘制 "video" 网络摄像头流的以下片段着色器。
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;
}
我的渲染函数设置如下:
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);
我不知道如何继续使网络摄像头显示为缩放比例和球体的一部分,而不是在其上拉伸。网络摄像头是一个 100 度的摄像头,应该放在球体内。
如果你的 UV 横跨整个球体,你可以将它整个用于背景图像采样,而将它的一小部分用于视频纹理采样。
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;
}
编辑:
这是可用的 shadertoy:https://www.shadertoy.com/view/MsdSWs
另一种方法是设置您的视频 UV 坐标,使 0<->1 范围代表您想要观看视频的区域
换句话说,背景的 UV 消失了
0,0 0.3 0.7 1.0
+------+------+------+
| | | |
| | | |
| | | |
0.3 +------+------+------+
| | | |
| | | |
| | | |
0.7 +------+------+------+
| | | |
| | | |
| | | |
1.0 +------+------+------+
但是视频 UV 消失了
-1,-1 0 1 2
+------+------+------+
| | | |
| | | |
| | | |
0 +------+------+------+
| |......| |
| |......| |
| |......| |
1 +------+------+------+
| | | |
| | | |
| | | |
2 +------+------+------+
这使得 ......
部分成为 0 和 1 之间的部分
那么你的着色器就是
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);
}