threejs坑记录-笔记

雪花

注意depthTest: false 否则会出现有transparent无效

const createSnow = () => {
  let map = new THREE.TextureLoader().load(snow);
  let material = new THREE.SpriteMaterial({
    map: map,
    transparent: true,
    side: THREE.DoubleSide,
    color: 0xffffff,
    blending: THREE.AdditiveBlending,
    fog: true,
    depthTest: false
  });
  return new THREE.Sprite(material);
};

const createEmitter = (camera, renderer) => {
  const emitter = new Emitter();
  const position = new Position();

  position.addZone(new BoxZone(5000, 10, 5000));

  return emitter
      .setRate(new Rate(new Span(34, 48), new Span(0.2, 0.5)))
      .addInitializers([
        new Mass(1),
        new Radius(new Span(10, 20)),
        position,
        new Life(5, 10),
        new Body(createSnow()),
        new RadialVelocity(0, new Vector3D(0, -1, 0), 90),
      ])
      .addBehaviours([
        new RandomDrift(10, 1, 10, 0.05),
        new Rotate('random', 'random'),
        new Gravity(10),
        new CrossZone(new ScreenZone(camera, renderer, 20, '234'), 'dead'),
      ])
      .setPosition({ y: 1200 })
      .emit();
};

const nebulaRenderer = new SpriteRenderer(scene, THREE);
  const system = new ParticleSystem();
  nebula = system
      .addEmitter(createEmitter(camera, renderer))
      .addRenderer(nebulaRenderer)

function animal() {
  if (nebula) {
    nebula.update();
  }
  renderer.render(scene, camera)
  requestAnimationFrame(animal)

}

重叠显示闪烁

在这里插入图片描述
logarithmicDepthBuffer - 是否使用对数深度缓存。如果要在单个场景中处理巨大的比例差异,就有必要使用

解决办法:
renderer = new THREE.WebGLRenderer( { antialias: true, logarithmicDepthBuffer: true } );
或者
.depthTest属性值默认true,设置为false可以关闭深度测试.

Raycaster intersectObject报错

在这里插入图片描述

Cannot read properties undefined(reading ‘side’)

解决方法: 这个报错是因为Mesh有多个材质,可以自己输出Material属性看下,是个数组导致的。我临时的解决办法是 把Material的值由数组改为对象
在这里插入图片描述

如何生成中文字体

首先下载思源ttf字体。
http://www.diyiziti.com/download/220/
在这里插入图片描述
然然后在转换字体的网页的网站,转换成json字体。
https://gero3.github.io/facetype.js/
在这里插入图片描述

天空盒子

1、图片

 scene.background = new THREE.CubeTextureLoader()
     .setPath( '/imgs/' )
    .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ]);
    
 let textureCube = new THREE.CubeTextureLoader()
      .setPath('/sky/')
      .load(['Left.jpg', 'Right.jpg', 'Up.jpg', 'Down.jpg', 'Back.jpg', 'Front.jpg']);
  scene.background = textureCube;

2、hdr

import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader';
import {PMREMGenerator} from 'three/src/extras/PMREMGenerator'
var texLoader = new RGBELoader();
const pmremGenerator = new PMREMGenerator(renderer); // 使用hdr作为背景色
pmremGenerator.compileEquirectangularShader();
texLoader.load('/model/model.hdr', function(texture) {
    const envMap = pmremGenerator.fromEquirectangular(texture).texture;
    pmremGenerator.dispose();
    scene.environment = envMap; // 给场景添加环境光效果
    scene.background = envMap;
})

添加视频

let video = document.createElement('video');
    video.src = "/imgs/1.mp4";
    video.autoplay = true
    video.loop = true
    video.muted=true
    video.preload = "auto";
    video.play();
    let texture = new THREE.VideoTexture(video)
    texture.needsUpdate = true;
    let geometry = new THREE.PlaneGeometry(250, 180); //矩形平面
    let material = new THREE.MeshBasicMaterial({
        color: 0xffffff,
        map: texture, // 设置纹理贴图
        side: THREE.DoubleSide
    }); //材质对象Material
    let mesh = new THREE.Mesh(geometry, material);
    mesh.position.set(2579.405241545493, -181.51372808235914 + 100, 150.91691453263547);
    return mesh

let renderer = new THREE.WebGLRenderer({
    antialias: true, //开启锯齿
    alpha: true,
    logarithmicDepthBuffer: true
});

sketchup能够为模型减面

OrbitController参数

// Set to false to disable this control
//鼠标控制是否可用
	this.enabled = true;

// "target" sets the location of focus, where the object orbits around
//聚焦坐标
	this.target = new THREE.Vector3();

// How far you can dolly in and out ( PerspectiveCamera only )
//最大最小相机移动距离(景深相机)
	this.minDistance = 0;
	this.maxDistance = Infinity;

// How far you can zoom in and out ( OrthographicCamera only )
//最大最小鼠标缩放大小(正交相机)
	this.minZoom = 0;
	this.maxZoom = Infinity;

// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
//最大仰视角和俯视角
	this.minPolarAngle = 0; // radians
	this.maxPolarAngle = Math.PI; // radians

// How far you can orbit horizontally, upper and lower limits.
// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
//水平方向视角限制
	this.minAzimuthAngle = - Infinity; // radians
	this.maxAzimuthAngle = Infinity; // radians

// Set to true to enable damping (inertia)
// If damping is enabled, you must call controls.update() in your animation loop
//惯性滑动,滑动大小默认0.25
	this.enableDamping = false;
	this.dampingFactor = 0.25;

// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
// Set to false to disable zooming
//滚轮是否可控制zoom,zoom速度默认1
	this.enableZoom = true;
	this.zoomSpeed = 1.0;

// Set to false to disable rotating
//是否可旋转,旋转速度
	this.enableRotate = true;
	this.rotateSpeed = 1.0;

// Set to false to disable panning
//是否可平移,默认移动速度为7px
	this.enablePan = true;
	this.keyPanSpeed = 7.0;	// pixels moved per arrow key push

// Set to true to automatically rotate around the target
// If auto-rotate is enabled, you must call controls.update() in your animation loop
//是否自动旋转,自动旋转速度。默认每秒30圈
	this.autoRotate = false;
	this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60

// Set to false to disable use of the keys
//是否能使用键盘
	this.enableKeys = true;

// The four arrow keys
//默认键盘控制上下左右的键
	this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };

// Mouse buttons
//鼠标点击按钮
	this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };

要素

1、group
2、renderer
3、scene
4、camera
5、controls

threejs性能优化

https://blog.pig1024.me/posts/621a1fea23cc38439fdbc85d

相机居中渲染


        let box3 = new THREE.Box3()
        box3.expandByObject(this.allModel) // 计算模型包围盒
        let size = new THREE.Vector3()
        box3.getSize(size) // 计算包围盒尺寸
        let center = new THREE.Vector3()
        box3.getCenter(center) // 计算一个层级模型对应包围盒的几何体中心坐标

        function maxSize(vec3) {
          var max;
          if (vec3.x > vec3.y) {
            max = vec3.x
          } else {
            max = vec3.y
          }
          if (max > vec3.z) {} else {
            max = vec3.z
          }
          return max;
        }

        let camera = new THREE.PerspectiveCamera(30, width / height, 1, 2000)
        let max = maxSize(size); //包围盒长宽高中最大的一个值,用来表征模型的尺寸
        // 1.控制渲染范围,但是不要忘记相机位于模型包围盒之外
        camera.position.copy(center.clone().addScalar(max * 0.5));
        // 2. 居中渲染:设置相机目标观察点,指向包围盒几何中心
        camera.lookAt(center);
        // 3.注意near和far尺寸控制
        camera.near = max*0.1;//最好和相机位置或者说包围盒关联,别设置0.1 1之类看似小的值
        camera.far = max * 3;//根据相机位置和包围大小设置,把包围盒包含进去即可,宁可把偏大,不可偏小
        camera.updateProjectionMatrix();//渲染范围改变,注意更新投影矩阵
        let controls = new OrbitControls(camera, renderer.domElement)
        controls.target.copy(center);
        controls.update()

three.js orbitcontrol更改绕x轴与z轴旋转

我们在threejs模型中可以引入orbitcontrol来控制模型交互动作,但orbitcontrol默认是以y轴为正向上轴,即旋转的时候绕x轴和y轴旋转
但我现在想让绕x轴和z轴旋转,方法是

camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
                camera.position.z = 2900;
                //关键就是设置camera的up为y轴
                camera.up = new THREE.Vector3(0, 0, 1);
                scene.add(camera);

A WebGL context could not be created. Reason: Web page caused context loss and was blocked

https://support.google.com/chrome/thread/25018979/status-could-not-create-a-webgl-context?hl=en

UV坐标
在这里插入图片描述

Canvas画布加载图片

如果作为纹理贴图使用的Canvas画布加载了图片,注意在图片加载完成的时候更新Threejs相关模型的纹理贴图。如果不更新纹理,你会发现canvas画布上的图片无法现在是Threejs模型的纹理上。

var canvas = document.createElement(“canvas”);

var ctx = canvas.getContext(‘2d’);
var Image = new Image();
Image.src = “./贴图.jpg”;
Image.onload = function() {
var bg = ctx.createPattern(Image, “no-repeat”);

// 注意图片加载完成执行canvas相关方法后,要更新一下纹理
texture.needsUpdate = true;
}

渲染参数

renderer = new THREE.WebGLRenderer({
antialias: true, //开启锯齿,
})
renderer.physicallyCorrectLights = true;
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.setClearColor(0x6495ED);
renderer.toneMappingExposure = 0.5;

鱼眼效果

漫游

function createCure2() {
  let geometry = new THREE.BufferGeometry(); //创建一个缓冲类型几何体
  let line1 = new THREE.LineCurve3(
      new THREE.Vector3(175.52462898895072, 16.545, 265.0279404510418),
      new THREE.Vector3(45.42388223222965, 16.545, 68.37845995291991));
  manyouCure = new THREE.CurvePath();

  let line2 = new THREE.LineCurve3(
      new THREE.Vector3(45.42388223222965, 16.545, 68.37845995291991),
      new THREE.Vector3(199.35339268360357, 16.545, -94.99382829094)
  )

  let line3 = new THREE.LineCurve3(
      new THREE.Vector3(199.35339268360357, 16.545, -94.99382829094),
      new THREE.Vector3(83.607, 6.458, 26.067)
  )

  let line4 = new THREE.LineCurve3(
      new THREE.Vector3(83.607, 6.458, 26.067),
      new THREE.Vector3(126.538, 4.049, 106.781)
  )

  let line5 = new THREE.LineCurve3(
      new THREE.Vector3(126.538, 4.049, 106.781),
      new THREE.Vector3(106.223, 4.049, 102.008)
  )

  let line6 = new THREE.LineCurve3(
      new THREE.Vector3(106.223, 4.049, 102.008),
      new THREE.Vector3(68.316, 4.049, 75.350)
  )

  manyouCure.curves.push(line1, line2, line3, line4, line5, line6);
  let personPointArr = manyouCure.getSpacedPoints(1999); //分段数100,返回101个顶点
  geometry.setFromPoints(personPointArr);
}

function manyou() {
  if (roamValue && manyouCure) {
    if (manyouPointPercent >= 0.99) {
      manyouPointPercent = 0;
    }
    manyouPointPercent += 0.0005;

    let curePosition = manyouCure.getPointAt(manyouPointPercent);
    let dir = manyouCure.getTangentAt(manyouPointPercent);
    let newer = new THREE.Vector3(dir.x, 0, dir.z);

    let target2 = curePosition.clone();
    target2.y = target2.y;
    target2.sub(newer.clone().multiplyScalar(10));

    let target3 = curePosition.clone();
    target3.y = target3.y;
    target3.add(newer.clone().multiplyScalar(0.01));

    camera.position.copy(target2)
    camera.lookAt(target3);
  }
}

双击正确姿势

webgl.value.addEventListener('dblclick', (event) => {
    let Sx = event.offsetX; //鼠标单击位置横坐标
    let Sy = event.offsetY; //鼠标单击位置纵坐标
    //屏幕坐标转WebGL标准设备坐标
    let x = (Sx / renderer.domElement.clientWidth) * 2 - 1; //WebGL标准设备横坐标
    let y = -(Sy / renderer.domElement.clientHeight) * 2 + 1; //WebGL标准设备纵坐标
    let raster = new THREE.Raycaster();
    raster.setFromCamera(new THREE.Vector2(x, y), camera);
    let intersects = raster.intersectObjects(scene.children);
    if (intersects.length > 0) {// 判断参数[boxMesh]中模型对象是否与射线相交
      console.log("选中的对象", intersects[0])
      console.log("射线投射器返回的对象 点point", intersects[0].point);
      console.log('相机的位置', camera.position)
    }
  })
function onMouseDbClick(event) {
	//声明raycaster和mouse变量
	let raycaster = new THREE.Raycaster();
	let mouse = new THREE.Vector2();
	let map = document.getElementById('map');
	//通过鼠标点击的位置计算出raycaster所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.
	// mouse.x = (event.offsetX / map.scrollWidth) * 2 - 1;
	// mouse.y = -(event.offsetY / map.scrollHeight) * 2 + 1;
	console.log()
	mouse.x = ((event.clientX - map.getBoundingClientRect().left) / map.offsetWidth) * 2 - 1
	mouse.y = -((event.clientY - map.getBoundingClientRect().top) / map.offsetHeight) * 2 + 1
	console.log(mouse)
	// 通过鼠标点的位置和当前相机的矩阵计算出raycaster
	raycaster.setFromCamera(mouse, CAMERA);
	// 获取raycaster直线和所有模型相交的数组集合
	let intersects = raycaster.intersectObjects(SCENE.children);
	console.log(intersects);
	if (intersects.length > 0) {// 判断参数[boxMesh]中模型对象是否与射线相交
		console.log("选中的对象", intersects[0])
		console.log("射线投射器返回的对象 点point", intersects[0].point);
		console.log('相机的位置', CAMERA.position)
	}
}

Three.js使用OrbitControls后修改相机旋转方向无效

在这里插入图片描述

设置透明无效

RENDERER = new THREE.WebGLRenderer({
		antialias: true, //抗锯齿
		precision:'highp'
	});
	RENDERER.sortObjects = false, 就是这个导致的

选点工具

https://l7editor.antv.antgroup.com/

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Three.js中,深度测试是用来确定哪些物体在渲染时应该显示在前面,哪些应该显示在后面的一种技术。默认情况下,深度测试是开启的,可以通过设置renderer的depthTest属性为false来关闭深度测试。例如,可以使用以下代码来创建一个开启了抗锯齿和对数深度缓冲的WebGL渲染器: ```javascript renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true }); ``` 另外,如果在使用Raycaster的intersectObject方法时遇到报错,可能是因为没有正确加载纹理。在加载纹理图片后,需要在图片加载完成后更新纹理,可以通过设置texture的needsUpdate属性为true来实现。例如: ```javascript var canvas = document.createElement("canvas"); var ctx = canvas.getContext('2d'); var Image = new Image(); Image.src = "./贴图.jpg"; Image.onload = function() { var bg = ctx.createPattern(Image, "no-repeat"); // ... // 注意图片加载完成执行canvas相关方法后,要更新一下纹理 texture.needsUpdate = true; } ``` 此外,如果想要在Three.js中使用orbitcontrol来控制模型的交互动作,并且希望绕x轴和z轴旋转,可以通过设置camera的up属性来实现。例如: ```javascript camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000); camera.position.z = 2900; // 关键就是设置camera的up为y轴 camera.up = new THREE.Vector3(0, 0, 1); scene.add(camera); ``` 最后,如果在使用Three.js时遇到"A WebGL context could not be created. Reason: Web page caused context loss and was blocked"的错误,可能是由于WebGL上下文丢失导致的。这可能是由于浏览器的安全策略或其他原因引起的。可以尝试重新加载页面或检查浏览器的设置来解决这个问题。 #### 引用[.reference_title] - *1* *2* *3* [threejs记录-笔记](https://blog.csdn.net/u010568976/article/details/122562413)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值