Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Three.js 多纹理重叠webGL_Three.js_Glsl_Webgl_Fragment Shader - Fatal编程技术网

Three.js 多纹理重叠webGL

Three.js 多纹理重叠webGL,three.js,glsl,webgl,fragment-shader,Three.js,Glsl,Webgl,Fragment Shader,我有两个对象需要使用WebGLRenderTarget在两个不同的纹理中渲染。使用着色器将两个纹理映射到一个平面,然后将该平面添加到主场景后,我在绘制更接近的对象时遇到问题 我创建了一个JSFIDLE来显示我的问题: 真正的魔法发生在这里: void main() { vec4 color = texture2D(tex_sphere, vUv); vec4 color_cube = texture2D(tex_cube, vUv); gl_FragColor = ve

我有两个对象需要使用WebGLRenderTarget在两个不同的纹理中渲染。使用着色器将两个纹理映射到一个平面,然后将该平面添加到主场景后,我在绘制更接近的对象时遇到问题

我创建了一个JSFIDLE来显示我的问题: 真正的魔法发生在这里:

void main() {
    vec4 color = texture2D(tex_sphere, vUv);
    vec4 color_cube = texture2D(tex_cube, vUv);

    gl_FragColor = vec4(color.rgb * color_cube.rgb, 1.0);
}
球体相对于摄影机放置在立方体的前面。当球体像素重叠时,如何绘制球体像素而不是立方体


为了清楚起见,我试图找到一种方法来计算每个像素与相机的距离,并首先渲染较近的像素。通常,如果
tex_sphere
具有alpha通道,则可以通过alpha通道混合颜色:

void main()
{
    vec4 color = texture2D(tex_sphere, vUv);
    vec4 color_cube = texture2D(tex_cube, vUv);

    vec3 mixCol  = mix(color_cube.rgb, color.rgb, color.a);
    gl_FragColor = vec4(mixCol.rgb, 1.0);
}
如果
tex\u球体
具有黑色背景,则应忽略该背景,您必须检查
tex\u球体
的颜色是否不是黑色:

void main()
{
    vec4 color = texture2D(tex_sphere, vUv);
    vec4 color_cube = texture2D(tex_cube, vUv);

    vec3  test   = step(1.0/512.0, color.rgb);
    float a      = max(max(test.r, test.g), test.b);
    vec3  mixCol = mix(color_cube.rgb, color.rgb, a);
    gl_FragColor = vec4(mixCol.rgb, 1.0);
}

注意,根据[0.0,1.0]范围内的浮点插值值
a
,在2个值之间进行插值。如果
a
等于0.0,则返回第一个值;如果
a
等于1.0,则返回第二个值

测试值是否小于边值。如果小于0.0,则返回1.0


要获得黑色背景,必须在将球体渲染到渲染目标时设置黑色“透明”颜色:

function render() {
    controls.update();

    renderer.setClearColor(0x00);
    renderer.render(sphereScene, camera, renderTargets.sphere, true);

    renderer.setClearColor(0xccccff);
    renderer.render(cubeScene, camera, renderTargets.cube, true);

    renderer.setClearColor(0xccccff);
    renderer.render(scene, camera);
}
如果要使用alpha通道,则必须在渲染到渲染目标之前设置:

function render() {
    controls.update();

    renderer.setClearAlpha(0);
    renderer.render(sphereScene, camera, renderTargets.sphere, true);

    renderer.setClearAlpha(1);
    renderer.render(cubeScene, camera, renderTargets.cube, true);

    renderer.render(scene, camera);
}
var场景、渲染器、摄影机、控件;
立方变种,球形变种;
var渲染目标;
init();
制作动画();
函数init(){
场景=新的三个。场景();
cubeScene=new THREE.Scene();
sphereScene=new-THREE.Scene();
renderer=new THREE.WebGLRenderer({antialas:false,alpha:true});
渲染器.setClearColor(0xCCFF);
摄像头=新的三个透视摄像头(75,window.innerWidth/window.innerHeight,0.14000);
摄像机位置设置(0,0,200);
renderer.setSize(window.innerWidth、window.innerHeight);
控件=新的三个.轨道控件(摄影机、渲染器.doElement);
摄像机。注视(场景。位置);
var灯光=新的三个半球灯光(0xffffff,0x444444);
场景。添加(灯光);
container=document.createElement('div');
文件.正文.附件(容器);
container.appendChild(renderer.domeElement);
initObjects();
initRenderTargets(window.innerWidth、window.innerHeight);
}
函数onResize(){
renderer.setSize(window.innerWidth、window.innerHeight);
camera.aspect=window.innerWidth/window.innerHeight;
camera.updateProjectMatrix();
renderTargets.sphere.setSize(window.innerWidth、window.innerHeight);
renderTargets.cube.setSize(window.innerWidth、window.innerHeight);
}
函数initObjects(){
var cGeometry=新的三箱几何(100100100);
var cMaterial=新的三个.MeshBasicMaterial({color:0x00ff00});
var cube=新的三网格(cGeometry,cMaterial);
cube.position.z=-210;
立方体位置y=100;
var sGeometry=新的三种球墨法(75,32,32);
var sMaterial=新的3.0网格基本材质({
颜色:0xff0000
});
var sphere=新的三网格(S几何、S材料);
sphere.position.z=-100;
添加(球体);
添加(立方体);
}
函数initRenderTargets(宽度、高度){
renderTargets=createRenderTargets(宽度、高度);
变量={
“tex_cube”:{type:“t”,值:renderTargets.cube.texture},
“tex_sphere”:{类型:“t”,值:renderTargets.sphere.texture}
}
材质=新的三个材质材质材质({
制服:制服,
vertexShader:document.getElementById('vs_rt').textContent,
fragmentShader:document.getElementById('fs_rt').textContent
});
var plane=新的三个平面几何图形(宽度、高度);
四边形=新的三个网格(平面、材质);
场景。添加(四边形);
}
函数createRenderTargets(宽度、高度){
变量参数={
最小过滤器:三个。最近的过滤器,
磁过滤器:三个。最近的过滤器,
};
返回{
立方体:新的三个.WebGLRenderTarget(宽度、高度、参数),
球体:新的三个.WebGLRenderTarget(宽度、高度、参数)
};
}
函数animate(){
请求动画帧(动画);
render();
}
//------------------------------------------
//主渲染
//------------------------------------------
函数render(){
控件更新();
setClearAlpha(0);
renderer.render(sphereScene、camera、renderTargets.sphere、true);
setClearAlpha(1);
renderer.render(立方体、摄影机、renderTargets.cube、true);
渲染器。渲染(场景、摄影机);
}

均匀采样2D tex_立方体;
均匀采样二维特克斯球;
可变vec2 vUv;
void main(){
vUv=紫外线;
gl_位置=projectionMatrix*modelViewMatrix*vec4(位置,1.0);
}
均匀采样2D tex_立方体;
均匀采样二维特克斯球;
可变vec2 vUv;
void main(){
vec4颜色=纹理2d(tex_球体,vUv);
vec4 color_cube=纹理2D(tex_cube,vUv);
vec3 mixCol=mix(color_cube.rgb,color.rgb,color.a);
gl_FragColor=vec4(mixCol.rgb,1.0);
}

谢谢您的回答!这是一个很好的方法来控制哪个纹理被渲染到前面;但是,我希望渲染器渲染更接近的对象。例如,如果无法预测对象的放置位置,则无论其放置位置如何,使用alpha通道仍将在另一个纹理之前渲染一个纹理。本质上,我试图找到一种方法来计算每个像素与相机的距离,并首先渲染较近的像素
vWorldPosition=(modelMatrix*vec4(位置,1.)).xyz然后在着色器中浮动myDistanceToCamera=length(cameraPosition-VWorldPosition