threejs 正交投影 渲染顺序 renderorder

现在的问题是:正交投影下如果两个平面的Z值相同,先绘制哪个平面?试验一下

    const mesh1 = new Mesh(
      new PlaneGeometry(1000, 1000),
      new MeshBasicMaterial({ color: 0xff0000})
    );
    mesh1.name = "test1";
    const mesh2 = new Mesh(
      new PlaneGeometry(1000, 1000),
      new MeshBasicMaterial({ color: 0x00ff00})
    );
    mesh2.translateX(500);
    mesh2.name = "test2";
    scene.add(mesh1);
    scene.add(mesh2);

在这里插入图片描述
上面代码的执行结果是mesh2在上面。

    const mesh1 = new Mesh(
      new PlaneGeometry(1000, 1000),
      new MeshBasicMaterial({ color: 0xff0000})
    );
    mesh1.name = "test1";
    const mesh2 = new Mesh(
      new PlaneGeometry(1000, 1000),
      new MeshBasicMaterial({ color: 0x00ff00})
    );
    mesh2.translateX(500);
    mesh2.name = "test2";
    scene.add(mesh2);
    scene.add(mesh1);

注意:这个代码与第一个代码块的差别只是mesh加入到场景的顺序不同。

上面代码的执行结果如下图
在这里插入图片描述
两个代码块的执行结果相同,都是mesh2在上面。这与我刚开始想象的不同,我以为后加入场景的后绘制,因此第二个代码块的执行结果应该是mesh1红色在上面。

如果现在我就想mesh1红色在上面,怎么办?

这时可以引入renderorder。

    const mesh1 = new Mesh(
      new PlaneGeometry(1000, 1000),
      new MeshBasicMaterial({ color: 0xff0000})
    );
    mesh1.name = "test1";
    mesh1.renderOrder = 1;
    const mesh2 = new Mesh(
      new PlaneGeometry(1000, 1000),
      new MeshBasicMaterial({ color: 0x00ff00})
    );
    mesh2.translateX(500);
    mesh2.name = "test2";
    scene.add(mesh1);
    scene.add(mesh2);

注意:这个代码块与第一个代码块不同的是将mesh1的renderorder设为1。
在这里插入图片描述
结果如上图,跟我想象的一致。mesh1红色在上面了。

直接给出源码,解释一下上面现象的原因。

//下面代码在three.module.js
if ( _this.sortObjects === true ) {
    currentRenderList.sort( _opaqueSort, _transparentSort );
}

在threejs的render函数中会对渲染对象进行排序,就是上面的sort函数,具体实现在下面

function sort( customOpaqueSort, customTransparentSort ) {
	if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
	if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
	if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
}

我们在这里暂时只需要关注opaque.sort,customOpaqueSort是自定义的排序函数,painterSortStable是threejs内置的排序函数。由于我并没有指定customOpaqueSort,因此执行的是painterSortStable。
painterSortStable源码如下

function painterSortStable( a, b ) {
	if ( a.groupOrder !== b.groupOrder ) {
		return a.groupOrder - b.groupOrder;
	} else if ( a.renderOrder !== b.renderOrder ) {
		return a.renderOrder - b.renderOrder;
	} else if ( a.material.id !== b.material.id ) {
		return a.material.id - b.material.id;
	} else if ( a.z !== b.z ) {
		return a.z - b.z;
	} else {
		return a.id - b.id;
	}
}

看到这里就都明白了,解释了前面的现象。为什么改了renderorder之后mesh1就显示在上面,因为mesh1的renderorder大于mesh2的renderorder,因此被放到了renderlist后面,后渲染。

另外也解释了另外一个问题,为什么在第二个代码块中mesh1后加入场景,但是还是先绘制mesh2。其实是mesh2的material.id大于mesh1的material.id,并且判断material.id的优先级高于mesh.id。(但是我不知道为什么要这样安排)。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值