Three.js 多纹理重叠webGL
我有两个对象需要使用WebGLRenderTarget在两个不同的纹理中渲染。使用着色器将两个纹理映射到一个平面,然后将该平面添加到主场景后,我在绘制更接近的对象时遇到问题 我创建了一个JSFIDLE来显示我的问题: 真正的魔法发生在这里: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
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