【ThreeJs】利用DepthPeel技术,解决模型半透明出现的碎三角面问题

更新时间:2023-08-08 05:07:59 阅读: 评论:0

【ThreeJs 】利⽤DepthPeel 技术,解决模型半透明出现的碎三⾓⾯问题
在ThreeJS中,模型半透明设置只需要很简单的两⾏代码
留学的好处然⽽.....
我们的模型有时候出现这种情况,正⾯看半透明效果似乎正常,
正⾯看半透明效果似乎正常
⼀旦旋转到侧⾯,就会发现⼤量的碎三⾓⾯⽚(我的妈呀,这是什么⿁)
侧⾯看出现⼤量的碎三⾓⾯开始以为是模型数据问题,经过排查发现并⾮如此,这个半透明不是材质本⾝问题,⽽是绘制顺序。在OpenGL渲染中的解决⽅案是开启depth peeling,但素(41's tone),threejs中并没有这个选项,需要⾃⼰实现。
实现基本原理是芥末解释的
The idea is straight forward as shown by the name: we draw the objects multiple times. For each pas
采购职责
s, we peel one layer from front and one layer from back (front or back is purely depending on their depth, not if it’s from front face or back face).
主要实现函数如下:
1. depthOnbeforeCompile
1
curMat.opacity = 0.5 // 50%透明度ansparent = curMat.opacity < 1 // transparent 属性必须为True 才能半透明
孙权的儿子
2
3    shader.uniforms.uScreenSize = this.globalPeelUniforms.uScreenSize
4    shader.uniforms.uPrevDepthTexture = this.globalPeelUniforms.uPrevDepthTexture
5    shader.uniforms.uLayer = this.globalPeelUniforms.uLayer
6    shader.uniforms.uDepthOfft = this.globalPeelUniforms.uDepthOfft
癞蛤蟆吃什么
7    shader.uniforms.uDepthPeel = this.globalPeelUniforms.uDepthPeel
8
9    shader.fragmentShader = `
10                uniform vec2 uScreenSize;
11                uniform sampler2D uPrevDepthTexture;
12                uniform int uLayer;
13                uniform int uDepthPeel;
14                uniform float uDepthOfft;
15
16                ${shader.fragmentShader}
所以用英语怎么说
17            `
18    //peel depth
19    shader.fragmentShader = place(
20        /}$/gm,
21        `
22                    if(uDepthPeel == 0) return;
23
24                    if(uLayer != 0 ){
25
26                        vec2 screenPos = * uScreenSize;
27
28                        float prevDepth = unpackRGBAToDepth(texture2D(uPrevDepthTexture,screenPos));
29
30                        if(prevDepth + uDepthOfft - gl_FragCoord.z >= 0. ){
31                            discard;
32                        }
33                    }
34                }
35                `
36    )
37}
该函数在深度材质shader编译前(THREE.MeshDepthMaterial)和原始材质shader编译前中调⽤
1this.depthMaterial = new THREE.MeshDepthMaterial()
2this.depthMaterial.side = Side()
3this.depthMaterial.depthPacking = THREE.RGBADepthPacking
BeforeCompile = this.depthOnbeforeCompile.bind(this)
2. colorOnBeforeCompile
2    shader.fragmentShader = place('#include <packing>','')
3    shader.fragmentShader = `
4  #include <packing>
5  uniform sampler2D uPrevColorTexture;
6
7  ${shader.fragmentShader}
8  `海市蜃楼歌词
9    //this has early return
10    this.depthOnbeforeCompile(shader)
11
12    shader.fragmentShader = place(
13        /}$/gm,
14        `
15    *= gl_FragColor.a;
16  }
17  `
18    )
19}
该函数在原始材质shader编译前调⽤treat
1attach(node){
2    if (node.isMesh) {
3
4        derOrder = 1
5
6        ansparentObjects.push(node) // 索引,⽅便快速调⽤
7
8        BeforeCompile = lorOnBeforeCompile.bind(this);
9    }
10}
3.全局参数设置
1this.globalPeelUniforms = {
2    uLayer: { value: 0 },
3    uPrevDepthTexture: { value: null },
4    uPrevColorTexture: { value: null },
5    uScreenSize: { value: new THREE.Vector2(1,1) },
6    uDepthPeel: { value: Number(abled) },
7    uDepthOfft: { value: 0 },
8}
值得注意的是,this.globalPeelUniforms.uDepthPeel.value 作为是否开启半透明开关,⽽不是⽤threejs 默认的ansparent 属性。并且,ansparent 必须设置为fal,透明度依然由curMat.opacity控制。
4. 最后使⽤depth peel的render 替换threejs默认的der()
1
2render(renderer, scene, camera){
3
4    //clear main frame
5    renderer.tClearColor(0x000,1)
6    renderer.clear()
7
8    this.globalPeelUniforms.uLayer.value = 0
9
10    //render first depth
11    scene.overrideMaterial = this.depthMaterial
12    renderer.tClearColor(0xffffff,1)
13    der( scene, camera, this.targets[0], true)
14
15    //first color
16    scene.overrideMaterial = null
17    renderer.tClearColor(0x000,0)
18    der( scene, camera, this.targets[2], true)
19
20    for( let i = 0 ; i < this.options.layers ; i ++ ){
21
22        const a = i % 3 //shift the around
23        const b = (i+1) % 3
24        const c = (i+2) % 3
25        const d = 3 //peel into this
26
27        this.globalPeelUniforms.uPrevDepthTexture.value = this.targets[a]
28        this.globalPeelUniforms.uLayer.value = i + 1
29
30        //render next depth
31        scene.overrideMaterial = this.depthMaterial
32        renderer.tClearColor(0xffffff,1)
33        der( scene, camera, this.targets[b], true)
34
35        //peel
36        scene.overrideMaterial = null
环城37        renderer.tClearColor(0x000,0)
38        der( scene, camera, this.targets[d], true)
39
40        //combine
41        positeMaterial.uniforms.uTextureA.value = this.targets[c]
42        positeMaterial.uniforms.uTextureB.value = this.targets[d]
43        der( positeScene, camera, this.targets[a], true) 44
45    }
46
47    //render final result over opaque objects
48    this.globalPeelUniforms.uPrevDepthTexture.value = null
49
50    this. transparentObjects.forEach(o=>o.visible = fal)
51
52    der( scene, camera )
53    der( positeScene, camera )
54
55    ansparentObjects.forEach(o=>o.visible = true)
56
57
58    //der( this.debugScene , this.debugCamera )
59}
⼤功告成!最后效果如下:
在线

本文发布于:2023-08-08 05:07:59,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1127918.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:半透明   模型   材质   需要   问题
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图