![cover](https://img-blog.csdnimg.cn/dfa1e0d6c5274f06bcd335372f7e6851.png)
【Threejs】轮廓线、边框线、选中效果实现的N种方法以及性能评估(目前7种)
【Threejs】轮廓线、边框线、选中效果实现的N种方法以及性能评估(目前7种)对于模型较小,面数较少,机器性能很好的情况下,用哪种方法都可以。但是对于压缩后glb还有100m、200m,几百万面,机器配置又一般的情况下,对于效果和性能,就需要作出选择了。备注:① example里https://jsfiddle.net开头的链接,需要VPN,能访问国外网络,才能打开;②所有的性能评估,我是以
【Threejs】轮廓线、边框线、选中效果实现的N种方法以及性能评估(目前7种)
对于模型较小,面数较少,机器性能很好的情况下,用哪种方法都可以。
但是对于压缩后glb还有100m、200m,几百万面,机器配置又一般的情况下,对于效果和性能,就需要作出选择了。
备注:① example里https://jsfiddle.net开头的链接,需要VPN,能访问国外网络,才能打开;
②所有的性能评估,我是以 机器配置:CPU i5-4460 3.20GHz 、内存 8.00 GB、显卡 NVIDIA GeForce GTX 745 (4096MB) 上 运行压缩后100M 面数150w面左右的glb,在chrome上运行测试的。
OutlinePass
![image-20211129142212244](https://pxim.github.io/posts/62a2a9f8/image-20211129142212244.png)
example https://threejs.org/examples/?q=outline#webgl_postprocessing_outline
优点:效果非常赞,可设置 边线大小,光晕,边缘浓度,呼吸闪烁等等效果
缺点:性能消耗double
主要代码片段
// 引入
import {EffectComposer} from 'three/examples/jsm/postprocessing/EffectComposer.js';
import {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js';
import {ShaderPass} from 'three/examples/jsm/postprocessing/ShaderPass.js';
import {OutlinePass} from 'three/examples/jsm/postprocessing/OutlinePass.js';
import {FXAAShader} from 'three/examples/jsm/shaders/FXAAShader.js';
//初始化
// postprocessing
const size = renderer.getSize(new THREE.Vector2());
const _pixelRatio = renderer.getPixelRatio();
const _width = size.width;
const _height = size.height;
const renderTarget = new THREE.WebGLRenderTarget(
_width * _pixelRatio,
_height * _pixelRatio,
{
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBAFormat,
encoding: THREE.sRGBEncoding
}
);
renderTarget.texture.name = "EffectComposer.rt1";
composer = new EffectComposer(renderer, renderTarget);
// composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);
outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
composer.addPass(outlinePass);
// const textureLoader = new THREE.TextureLoader();
// textureLoader.load('assets/tri_pattern.jpg', function (texture) {
//
// outlinePass.patternTexture = texture;
// texture.wrapS = THREE.RepeatWrapping;
// texture.wrapT = THREE.RepeatWrapping;
//
// });
effectFXAA = new ShaderPass(FXAAShader);
effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
composer.addPass(effectFXAA);
outlinePass.visibleEdgeColor.set(outlineColor[0]); // 边缘可见部分发颜色 sColor[0].color
outlinePass.hiddenEdgeColor.set(outlineColor[1]); // 边缘遮挡部分发光颜色 sColor[1].color
outlinePass.edgeStrength = Number(10.0); //边框的亮度
outlinePass.edgeGlow = Number(1); //光晕[0,1]
outlinePass.edgeThickness = Number(1.0); //边缘浓度
outlinePass.pulsePeriod = Number(1.8); //呼吸闪烁的速度 闪烁频率 ,默认0 ,值越大频率越低
outlinePass.usePatternTexture = false; //是否使用父级的材质
outlinePass.downSampleRatio = 2; // 边框弯曲度
outlinePass.clear = true;
// animate render里
renderer.render(scene, camera);
composer.render();
EdgesGeometry
![image-20211129143940032](https://pxim.github.io/posts/62a2a9f8/image-20211129143940032.png)
example https://jsfiddle.net/tgcf1u84/3/
https://threejs.org/examples/?q=help#webgl_helpers
优点:效果还行;性能比OutlinePass,要好一点,但是差距不是很大,大概5-10fps的样子;代码实现简单;
缺点:性能消耗较大,效果一般,线框的宽度不能大于1(官方是这样解释的:由于OpenGL Core Profile与 大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。)
主要代码片段
//添加
var edgeMaterial = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 5,} );
object.traverse( function( child ) {
if ( child.isMesh ) {
var edges = new THREE.EdgesGeometry( child.geometry, 45 );
var line = new THREE.LineSegments( edges, edgeMaterial );
child.add( line );
}
} );
EdgesGeometry + LineSegments2
![image-20211129145651190](https://pxim.github.io/posts/62a2a9f8/image-20211129145651190.png)
example https://jsfiddle.net/5qv4Lmog/1/
优点:效果还行;线框宽度可大于1;性能比EdgesGeometry,要差一点,但是差距不是很大;
缺点:性能消耗较大,效果一般,不能在traverse时,直接add,否则会导致无尽的递归行为;
主要代码片段
//添加
edgeMaterial = new LineMaterial( { color: 0xff0000, linewidth: 5 } );
const meshes = [];
object.traverse( function( child ) {
if ( child.isMesh ) meshes.push( child );
} );
for ( let mesh of meshes ) {
var edges = new THREE.EdgesGeometry( mesh.geometry, 45 );
var wideEdges = new LineSegmentsGeometry().fromEdgesGeometry( edges );
var line = new LineSegments2( wideEdges, edgeMaterial );
mesh.add( line );
}
OutlineEffect
![image-20211129153423662](https://pxim.github.io/posts/62a2a9f8/image-20211129153423662.png)
example https://threejs.org/examples/?q=toon#webgl_materials_variations_toon (官方案例,单个scene)
https://jsfiddle.net/cwayd9v5/6/(多个scene,模拟实现特定对象出现边框线的效果)
优点:效果还行;性能也OK,代码实现很简单;
缺点:对于结构复杂的模型,不能实现特定对象出现边框线的功能效果(https://stackoverflow.com/questions/59997603/outline-effect-to-target-object/59998722#59998722 这个帖子上思路,能实现我提供的第二个效果,但是对于结构复杂模型,业务功能稍微复杂一些的,就不适用了);
主要代码片段
//引入
import { OutlineEffect } from './jsm/effects/OutlineEffect.js';
//初始化
let effect;
//renderer是webgl renderer
effect = new THREE.OutlineEffect(renderer,{
defaultThickness: 0.015, //线条粗细
defaultColor: [0.2,0.2,1], //线条颜色
efaultAlpha: 0.9,
// defaultKeepAlive: true // keeps outline material in cache even if material is removed from scene
});
//animate render里
effect.render( scene, camera ); //替换 renderer.render( scene, camera );
绘制一个对象两次;一次轮廓颜色对象,一次正常对象
![image-20211129160902045](https://pxim.github.io/posts/62a2a9f8/image-20211129160902045.png)
example https://jsfiddle.net/a4x0fwo7/47/
优点:效果还行;性能一般;
缺点:对于结构复杂的模型,会消耗较大的内存和性能;
主要代码片段
https://jsfiddle.net/a4x0fwo7/47/ 看这个链接里的源码
参考文章:https://blog.mozvr.com/cartoon-outline-effect/
法线延伸
![image-20211129161651781](https://pxim.github.io/posts/62a2a9f8/image-20211129161651781.png)
example https://omarshehata.github.io/csb-l01dp/
优点:未实现,不清楚
缺点:未实现,不清楚
主要代码片段
https://github.com/OmarShehata/webgl-outlines 看这个链接里的源码
参考文章:https://omar-shehata.medium.com/how-to-render-outlines-in-webgl-8253c14724f9
https://github.com/OmarShehata/webgl-outlines
BoxHelper
![image-20211129161901827](https://pxim.github.io/posts/62a2a9f8/image-20211129161901827.png)
example https://jsfiddle.net/maco6fqt/12/
https://threejs.org/examples/?q=box#webgl_helpers (官方案例)
优点:性能最好
缺点:效果比较差(这种效果只能算上选中效果,和边框线,轮廓线没关系)
主要代码片段
const box:any = new THREE.BoxHelper( object, '#00ffff'); //object 模型
object.attach(box);
更多推荐
所有评论(0)