threejs内发光和外发光

本文介绍如何使用Three.js实现地球大气层及辉光视觉效果,通过自定义shader来模拟从地球表面向外发散的大气辉光,并通过调整不透明度展现不同强度的光照效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考文章链接:使用threejs实现地球辉光和大气层效果

效果:
在这里插入图片描述
代码:


var vertexShader = [
    'varying vec3	vVertexWorldPosition;',
    'varying vec3	vVertexNormal;',
    'varying vec4	vFragColor;',
    'void main(){',
    '	vVertexNormal	= normalize(normalMatrix * normal);',//将法线转换到视图坐标系中
    '	vVertexWorldPosition	= (modelMatrix * vec4(position, 1.0)).xyz;',//将顶点转换到世界坐标系中
    '	// set gl_Position',
    '	gl_Position	= projectionMatrix * modelViewMatrix * vec4(position, 1.0);',
    '}'

].join('\n');
//大气层效果
THREE.AeroSphere = {
    uniforms: {
        coeficient: {
            type: "f",
            value: 1.0
        },
        power: {
            type: "f",
            value: 2
        },
        glowColor: {
            type: "c",
            value: new THREE.Color(0xffff00)
        }
    },
    vertexShader: vertexShader,
    fragmentShader: [
        'uniform vec3	glowColor;',
        'uniform float	coeficient;',
        'uniform float	power;',

        'varying vec3	vVertexNormal;',
        'varying vec3	vVertexWorldPosition;',

        'varying vec4	vFragColor;',

        'void main(){',
        '	vec3 worldCameraToVertex= vVertexWorldPosition - cameraPosition;',	//世界坐标系中从相机位置到顶点位置的距离
        '	vec3 viewCameraToVertex	= (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;',//视图坐标系中从相机位置到顶点位置的距离
        '	viewCameraToVertex	= normalize(viewCameraToVertex);',//规一化
        '	float intensity		= pow(coeficient + dot(vVertexNormal, viewCameraToVertex), power);',
        '	gl_FragColor		= vec4(glowColor, intensity);',
        '}'//vVertexNormal视图坐标系中点的法向量
        //viewCameraToVertex视图坐标系中点到摄像机的距离向量
        //dot点乘得到它们的夹角的cos值
        //从中心向外面角度越来越小(从钝角到锐角)从cos函数也可以知道这个值由负变正,不透明度最终从低到高
    ].join('\n')

//辉光效果Grow
THREE.GlowSphere = {
    uniforms: {
        coeficient: {
            type: "f",
            value: 0.0
        },
        power: {
            type: "f",
            value: 2
        },
        glowColor: {
            type: "c",
            value: new THREE.Color(0xff22ff)
        }
    },
    vertexShader: vertexShader,
    fragmentShader: [
        'uniform vec3	glowColor;',
        'uniform float	coeficient;',
        'uniform float	power;',

        'varying vec3	vVertexNormal;',
        'varying vec3	vVertexWorldPosition;',

        'varying vec4	vFragColor;',

        'void main(){',
        '	vec3 worldVertexToCamera= cameraPosition - vVertexWorldPosition;',	//世界坐标系中顶点位置到相机位置到的距离
        '	vec3 viewCameraToVertex	= (viewMatrix * vec4(worldVertexToCamera, 0.0)).xyz;',//视图坐标系中从相机位置到顶点位置的距离
        '	viewCameraToVertex	= normalize(viewCameraToVertex);',//规一化
        '	float intensity		= coeficient + dot(vVertexNormal, viewCameraToVertex);',
        '	if(intensity > 0.65){ intensity = 0.0;}',
        '	gl_FragColor		= vec4(glowColor, intensity);',
        '}'//vVertexNormal视图坐标系中点的法向量
        //viewCameraToVertex视图坐标系中点到摄像机的距离向量
        //dot点乘得到它们的夹角的cos值
        //从中心向外面角度越来越大(从锐角到钝角)从cos函数也可以知道这个值由负变正,不透明度最终从高到低
    ].join('\n')
}

//球体 辉光 大气层
    function shad() {        
        var material1 = new THREE.ShaderMaterial({
            uniforms: THREE.AeroSphere.uniforms,
            vertexShader: THREE.AeroSphere.vertexShader,
            fragmentShader: THREE.AeroSphere.fragmentShader,
            blending: THREE.NormalBlending,
            transparent: true,
            depthWrite:false
        });
        var material2 = new THREE.ShaderMaterial({
            uniforms: THREE.GlowSphere.uniforms,
            vertexShader: THREE.GlowSphere.vertexShader,
            fragmentShader: THREE.GlowSphere.fragmentShader,
            blending: THREE.NormalBlending,
            transparent: true
        });
        var sphere = new THREE.SphereBufferGeometry(16, 32, 32);
        var mesh = new THREE.Mesh(sphere, material1);
        scene.add(mesh);

        var sphere2 = new THREE.SphereBufferGeometry(10, 32, 32);
        var mesh2 = new THREE.Mesh(sphere2, material2);
        //mesh2.position.x = 15;
        scene.add(mesh2);
    }

### Three.js 中实现发光效果的方法 为了在 Three.js 场景中创建具有发光效果的对象,通常会采用后期处理技术来应用辉光或泛光效果。这可以通过 `UnrealBloomPass` 来完成,该方法允许开发者选择性地对某些对象施加这种视觉增强。 下面是一个具体的实例展示如何设置带有部光源的物体: #### 创建场景并加载必要的库文件 首先确保已经引入了 PostProcessing UnrealBloomPass 的相关脚本。这些扩展提供了所需的工具来进行高级图像合成操作。 ```html <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/three/examples/jsm/postprocessing/EffectComposer.js"></script> <script src="https://cdn.jsdelivr.net/npm/three/examples/jsm/postprocessing/RenderPass.js"></script> <script src="https://cdn.jsdelivr.net/npm/three/examples/jsm/postprocessing/BloomPass.js"></script> ``` #### 初始化渲染器、相机场景 定义基本结构以便后续添加其他组件。 ```javascript const renderer = new THREE.WebGLRenderer({ antialias: true }); document.body.appendChild(renderer.domElement); // 设置视窗大小适配浏览器窗口尺寸 renderer.setSize(window.innerWidth, window.innerHeight); window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.z = 5; scene.add(camera); ``` #### 添加几何体与材质 这里选择了球形作为演示主体,并赋予其基础的颜色属性。 ```javascript const geometry = new THREE.SphereBufferGeometry(1, 32, 32); const material = new THREE.MeshStandardMaterial({ color: '#ff6e40', }); const sphere = new THREE.Mesh(geometry, material); scene.add(sphere); ``` #### 配置 Bloom Pass 参数 通过调整阈值(threshold)、强度(strength)平滑度(knee),可以控制哪些部分会被照亮及其亮度程度。 ```javascript import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85); bloomPass.threshold = 0; // 控制多少亮度以上才会触发光照 bloomPass.strength = 2; // 发光强弱 bloomPass.radius = 0; // 光晕扩散范围 ``` #### 组合 Effect Composer 完成最终呈现 将默认渲染过程同自定义的效果通道结合起来,从而实现场景的整体美化。 ```javascript import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; composer = new EffectComposer(renderer); composer.addPass(new RenderPass(scene, camera)); composer.addPass(bloomPass); ``` #### 动画循环更新画面帧率 最后一步是持续刷新屏幕上的内容直到页面关闭为止。 ```javascript function animate() { requestAnimationFrame(animate); sphere.rotation.x += 0.01; sphere.rotation.y += 0.01; composer.render(); // 使用组合后的渲染流程代替原始render函数调用 } animate(); ``` 上述代码片段展示了利用 Three.js 结合 post-processing 库中的 `UnrealBloomPass` 实现了一个简单却有效的发光特效[^1]。此案例不仅限于静态模型;动态变化同样适用,只需适当修改动画逻辑即可适应更多应用场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值