js倒计时代码最简单的_Three.js实现最简单的xray透视效果

f1c9b432e31ac90ebb60fa72fb936a58.png

前几天公司领导一直让做个透视效果,此时想到了xray效果,翻阅网上尚未找到用WebGL实现的Xray(可能我太笨木有找到),倒是许多Unity3D实现Xray,毕竟这东西在游戏中用的会多一点。实现Xray的主题思想很简单,就是被遮挡区域特效处理,未遮挡区域正常绘制即可。在这里我们采用Unity3D绘制Xray原理即两个pass,在这里我两个pass处理成两个相同的mesh运用不同的材质(性能浪费,毕竟不需要所有的Mesh具有Xray效果。。。。)。

思路(Unity3D)

实现这个效果需要两个pass

1. 绘制被遮挡部分,即 深度测试 Greater ,且不写入 深度缓冲区(防止印象其他物体的深度对比),剩下的 xray效果就比较容易,同一 空间 下通过 点积 处理。

2. 正常绘制,即 深度测试 LEqual ,且写入 深度缓冲区(正常与其他物体遮挡)。

改成WebGL:

pass1

//第一个pass渲染被遮挡部分,采用顶点法向量与相加法线关系越靠近物体边缘颜色越深,即float rim = 1 - saturate(dot(normalize(i.normal),normalize(i.viewDir)));
materialXay=new ShaderMaterial({
	uniforms:{},
	vertexShader:'',
	fragmentShader:'',
	transparent:true,
	depthWrite:false,
	depthFunc:GreaterDepth
});
pass2

//第二个pass正常渲染,会自动屏蔽被遮挡的部分
materialNormal=new ShaderMaterial({
	uniforms:{},
	vertexShader:'',
	fragmentShader:'',
	transparent:false,
	depthWrite:true,
	depthFunc:LessEqualDepth
});

示例代码

pass1的顶点着色器:

            varying vec3 vNormal;
            varying vec3 vPositionNormal;
            void main() 
            {
                vNormal = normalize( normalMatrix * normal ); // 转换到视图空间
                vPositionNormal = normalize(( modelViewMatrix * vec4(position, 1.0) ).xyz);
                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            }

pass1的片源着色器:

            uniform vec3 glowColor;
            uniform float bias;
            uniform float power;
            uniform float scale;
            varying vec3 vNormal;
            varying vec3 vPositionNormal;
            void main() 
            {
                float a = pow( bias + scale * abs(dot(vNormal, vPositionNormal)), power );
                gl_FragColor = vec4( glowColor, a );
            }

该段着色器效果发光效果参考:

无牙:用shader写一个发光材质​zhuanlan.zhihu.com
3bff1586dcc5b98804ab15cdb4925e64.png

最终pass1的材质:

	       let uniformsXary ={
                        scale:   { type: "f", value: -1.0},
                        bias:   { type: "f", value: 1.0},
                        power:   { type: "f", value: 1.4 },
                        glowColor: { type: "c", value: new THREE.Color(0x00ffff) }
                }
                let materialXay=new THREE.ShaderMaterial({
                    uniforms:uniformsXary,
                    vertexShader:document.getElementById( 'vertexshader').textContent,
                    fragmentShader: document.getElementById( 'fragmentshader').textContent,
                    transparent:true,
                    depthWrite:false,
                    depthTest:true,
                    depthFunc:THREE.GreaterDepth
                });

mesh示例:

                var loader = new FBXLoader();
				loader.load( './Asset/fbx/Samba Dancing.fbx', function ( object ) {
					object.traverse( function ( child ) {
						if ( child.isMesh ) {
                            //为了解决z冲突
                            let materialnormal=child.material;
                            materialnormal.polygonOffset = true;
                            materialnormal.depthTest = true;
                            materialnormal.polygonOffsetFactor = 1;
                            materialnormal.polygonOffsetUnits = 1.0;
							child.castShadow = true;
							child.receiveShadow = true;
                            let sphereGeomXay=child.geometry.clone();
                            let meshXay=new THREE.Mesh(sphereGeomXay,materialXay);
                            scene.add( meshXay );
						}

					} );
					scene.add( object );
				} );

最终实现的效果:

知乎视频​www.zhihu.com

思路扩展:可以将Scene中所有的Mesh(不运用Xray特效的mesh显示,同时关闭所有运用Xray特效的mesh,拍一张深度图,此深度图仅渲染不运用Xray特效mesh的Z值,传入到Xary特效着色器中,通过投影纹理获取相同位置z值,即当前着色器z值与通过获取深度图z进行对比,一次判断是否遮挡,在进行逻辑操作),这个我还在试,如果可以,我会写出来详细过程。原谅我语言表达很烂。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值