Skip to content

案例展示

创建点光源,立方体线框为点光源辅助器

<template>
  <div id="TO"></div>
</template>

<script setup>
import { onMounted } from 'vue';

onMounted(() => {
  //初始化场景
  let TO = new ThingOrigin("fileModel", document.getElementById("TO"), {
    scene: {
       ground:{ // 地面
        active: false,
      },
      background: {
        type: 'color',//设置背景颜色
        color: {
          alpha: 1, // 透明度 取值范围0~1
          color: "#999999",// 背景颜色
        },
      },
    },
    camera: { //相机
      position: {
        x: 0,
        y: 0,
        z: 20,
      }
    },
    lights: [ //设置环境光
      {
        name: "light1",
        type: "AmbientLight",
        color: '#404040',
        intensity: 0.3,
        visible: true
      },
    ],
    helper: {//辅助工具
      axes: {
        active: false,
      },
      grid: {
        active: false,
      },
    }
  })
  //顶点着色器代码片段(在下面创建着色器材质时,作为参数传入)
  var vertexShader = `
                    varying vec3 vNormal;
                    varying vec4 vWorldPosition;
                    
                    void main() {
                        vNormal = normalize(normalMatrix * normal);
                        vWorldPosition = modelMatrix * vec4(position, 1.0);
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                    }
                `;

  //片元着色器代码片段(RGBA分量操作,在下面创建着色器材质时,作为参数传入)
  var fragmentShader = `
                    uniform vec3 baseColor;
                    uniform vec3 lightDirection;
                    uniform float lightIntensity;
                    
                    varying vec3 vNormal;
                    varying vec4 vWorldPosition;
                    
                    // 卡通着色 - 将光照强度分为几个阶梯
                    float cartoonShading(float dotProduct) {
                        // 将dotProduct映射到0-1范围
                        float lightFactor = max(0.0, dotProduct);
                        
                        // 创建3个光照级别
                        if (lightFactor > 0.8) return 1.0;
                        if (lightFactor > 0.4) return 0.7;
                        return 0.4;
                    }
                    
                    void main() {
                        // 计算光照方向(从片段到光源)
                        vec3 lightDir = normalize(lightDirection - vWorldPosition.xyz);
                        
                        // 计算法线与光照方向的点积
                        float dotProduct = dot(vNormal, lightDir);
                        
                        // 应用卡通着色
                        float shading = cartoonShading(dotProduct);
                        
                        // 最终颜色
                        gl_FragColor = vec4(baseColor * shading, 1.0);
                    }
                `

  //创建着色器材质
  var shaderMaterial = TO.material.initShaderMaterial({
    vertexShader,
    fragmentShader,
    uniforms: {
      baseColor: { value: TO.tool.initColor(0x36CFC9) },
      lightDirection: { value: TO.tool.initVector3() },
      lightIntensity: { value: 1.0 },
      shadowMap: { value: null },
      shadowMapSize: { value: TO.tool.initVector2() },
      shadowCameraNear: { value: 0.5 },
      shadowCameraFar: { value: 50 }
    }
  })

  // 光源旋转参数
  let isRotating = true;
  let rotationAngle = 0;
  const lightDistance = 10; // 光源围绕球体旋转的半径
  const sphereRadius = 3;   // 球体半径

  //创建球体
  let sphere = TO.model.initSphere({
    base: {
      radius: sphereRadius,
      widthSegments: 64,
      heightSegments: 64,
    },
  });
  sphere.material = shaderMaterial;
  //添加到场景中
  TO.scene.add(sphere);

  //添加点光源, 使得球体和点光源一起旋转
  const pointLight = TO.light.addPointLight({
    name: "pointLight1",
    color: 0xffffff,
    intensity: 1.5,
    distance: 10,
    decay: 2,
    castShadow: true,
    shadowNear: 0.5,
    shadowFar: 50,
    shadowMapSize: 1024
  });
  // 后续添加辅助工具
  let lightHelper = null;
  if (pointLight) {
    lightHelper = TO.light.addPointLightHelper(pointLight, 0.5, 0x00ff00);
    if (lightHelper) {
      console.log('为 pointLight 创建的PointLightHelper');
    }
  }

  // 更新光源位置
  function updateLightPosition() {
    // 使用三角函数计算围绕球体的圆形路径上的位置
    const x = Math.cos(rotationAngle) * lightDistance;
    const z = Math.sin(rotationAngle) * lightDistance;

    // 设置光源位置
    pointLight.position.set(x, 0, z);
    lightHelper.update();

    // 更新材质中的光照方向
    if (sphere.material.uniforms && sphere.material.uniforms.lightDirection) {
      sphere.material.uniforms.lightDirection.value.copy(pointLight.position);
    }

    // 增加旋转角度
    if (isRotating) {
      rotationAngle += 0.01;
    }
  }

  // 动画循环
  function animate() {
    requestAnimationFrame(animate);
    // 更新光源位置
    updateLightPosition();
  }
  // 开始动画循环
  animate();
});
</script>

<style scoped>
#TO {
  width: 100%;
  height: 400px;
  position: relative;
}
</style>

API 介绍

light.addPointLight

方法签名返回值描述
addPointLight(params: PointLightOptions = {})PointLight创建点光源

PointLightOptions 参数说明:

参数名说明类型必填默认值
color灯光颜色number-0xffffff
intensity光照强度number-1
distance光照距离number-0
decay光照衰减系数number-1
position灯光位置,格式为 [x, y, z]array-[0, 10, 0]
castShadow是否投射阴影boolean-false
shadowNear阴影近平面距离number-0.5
shadowFar阴影远平面距离number-500
shadowMapSize阴影贴图尺寸number-1024
name点光源名称,默认格式为 pointLight_${时间戳}string-pointLight_${Date.now()}
helper是否显示灯光辅助线boolean-false
helperSize灯光辅助线尺寸number-1
helperColor灯光辅助线颜色undefined-undefined