three 中基础网格材质

316 阅读5分钟

在 three 中材质大约分三个类,网格材质,线材质,与其他材质,其中线材质主要针对 three 中的线段渲染,而网格材质主要针对的时几何体的渲染,还有其他材质,例如点精录,阴影材质,着色器材质,这些只有在特殊情况才会用到

MeshBasicMaterial 基础网格材质 有 17 个属性

基础网格材质是一种不受光影晌的材质,如果几何体不需要与光做任何交互这种材质是非常合适的一种,在使用alphaMap 时需要注意 开启透明 transparent 设置为 true 才能使纹理透明生效。aoMap需要第二组UV 在这里说下UV是什么,uv2 是几何体的属性,UV 坐标用于定义如何将 2D 纹理映射到 3D 网格上。还有一点要注意红色通道是指的灰度 灰度 这个贴图一般都是黑白的,或灰色的。在使用 combine 时要注意可以使用 reflectivity 控制贴图对表面的影晌。对于envMap与refractionRatio 与 specularMap 属性虽然基础材质中有这个属性但是这几个属性不透用于基础材质。

  • alphaMap 值类型 texture 用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。
  • aoMap 该纹理的红色通道用作环境遮挡贴图。默认值为null。aoMap需要第二组UV。
  • aoMapIntensity 环境遮挡效果的强度。默认值为1。零是不遮挡效果。
  • color 材质的颜色
  • combine 如何将表面颜色的结果与环境贴图(如果有)结合起来。选项为THREE.MultiplyOperation(默认值),THREE.MixOperation, THREE.AddOperation。如果选择多个,则使用.reflectivity在两种颜色之间进行混合。
  • envMap 环境贴图。默认值为null。
  • fog 是否支持雾,默认 true
  • lightMap 光照贴图。默认值为null。lightMap需要第二组UV。
  • lightMapIntensity 烘焙光的强度。默认值为1。
  • map 颜色贴图。可以选择包括一个alpha通道,通常与.transparent 或.alphaTest。默认为null。
  • reflectivity 环境贴图对表面的影响程度; 见.combine。默认值为1,有效范围介于0(无反射)和1(完全反射)之间。
  • refractionRatio 空气的折射率(IOR)(约为1)除以材质的折射率。它与环境映射模式THREE.CubeRefractionMapping 和THREE.EquirectangularRefractionMapping一起使用。 The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material. It is used with environment mapping mode THREE.CubeRefractionMapping. 折射率不应超过1。默认值为0.98。
  • wireframe 将几何体渲染为线框。默认值为false(即渲染为平面多边形)。
  • wireframeLinecap 定义线两端的外观。可选值为 'butt','round' 和 'square'。默认为'round'。
  • wireframeLinejoin 定义线连接节点的样式。可选值为 'round', 'bevel' 和 'miter'。默认值为 'round'。
  • wireframeLinewidth 控制线框宽度。默认值为1。 下面是一些简单的使用示例协助理解这些属性
<template>
    <div id="parkingLot" ref="parkingLot">
    </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import * as THREE from 'three';
import { PMREMGenerator } from 'three/src/extras/PMREMGenerator.js';
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
import redbgImage from "@public/redbg.png"
import banner2 from "@public/banner2.jpg"
import rgImage from "@public/rg.png"
import hdrImg from "@public/hdr/bgImage.hdr"
import rgImageban from "@public/person.jpg"
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
const parkingLot = ref();

onMounted(() => {
    const DOMEl = parkingLot.value;
    // 获取 DOMEl 的宽度和高度,以设置渲染器的大小。
    const width = DOMEl.clientWidth;
    const height = DOMEl.clientHeight;

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize( width, height );

    DOMEl.appendChild( renderer.domElement );
    const scene = new THREE.Scene();
    renderer.shadowMap.enabled = true; // 启用阴影映射
    const camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );
    camera.position.set( 0, 300, 800 );
    camera.lookAt( 0, 0, 0 );

    
    // 创建 PMREM 生成器
    const pmremGenerator = new PMREMGenerator(renderer);

    // 使用 RGBELoader 加载 HDR 环境图
    new RGBELoader().load(hdrImg, (hdrTexture) => {

        // 从 HDR 图像生成 PMREM 贴图
        const pmremTexture = pmremGenerator.fromEquirectangular(hdrTexture).texture;

        scene.background = pmremTexture;   // 作为背景图像
        scene.environment = pmremTexture;  // 作为全局环境贴图

        const geometry = new THREE.TorusKnotGeometry( 10, 4, 100, 16 );
        // 创建一个 ImageLoader 实例
        const loader = new THREE.TextureLoader();

        // 加载图像文件
        const texture = loader.load(rgImage);
        const material = new THREE.MeshBasicMaterial({
            color: 0xffff00,
            alphaMap: texture,
            transparent: true,  // 开启透明度
        });
        const torusKnot = new THREE.Mesh(geometry, material);
        scene.add(torusKnot);


        // 创建几何体
        const geometry1 = new THREE.BoxGeometry(10, 10, 10);

        // 复制第一组 UV 坐标作为第二组 UV 坐标
        geometry1.setAttribute('uv2', new THREE.BufferAttribute(geometry1.attributes.uv.array, 2));

        const baseTexture = loader.load(rgImageban);
        // 创建材质
        const material1 = new THREE.MeshBasicMaterial({
            map: baseTexture,
            aoMap: texture,
            aoMapIntensity: 1, // 控制环境遮挡效果的强度
        });

        // 创建网格对象
        const mesh = new THREE.Mesh(geometry1, material1);
        mesh.position.x = 50;
        scene.add(mesh);

        
        // 创建几何体
        const geometry2 = new THREE.BoxGeometry(10, 10, 10);

        const redbgImageTexture = loader.load(redbgImage);
        // 创建材质
        const material2 = new THREE.MeshBasicMaterial({
            color: 0x0000ff,
            map: redbgImageTexture,
            combine: THREE.MixOperation
        });

        // 创建网格对象
        const mesh2 = new THREE.Mesh(geometry2, material2);
        mesh2.position.x = -50;
        scene.add(mesh2);

        // 假设你已经加载了六个图像作为立方体贴图的面
        const loaderCube = new THREE.CubeTextureLoader();
        const cubemap = loaderCube.load([
            banner2, banner2,
            banner2, banner2,
            banner2, banner2
        ]);

        
        // 创建几何体
        const geometry3 = new THREE.BoxGeometry(10, 10, 10);
        console.log(pmremGenerator,"pmremGenerator")

        
        // 从立方体贴图生成 PMREM 贴图
        const pmremTexture2 = pmremGenerator.fromCubemap(cubemap).texture;

        // 创建材质
        const material3 = new THREE.MeshStandardMaterial({
            envMap: pmremTexture2,
            roughness: 0.1,// 光滑度,0 完全光滑  1 表面非常粗粗
            metalness: 0.9 // 反射属性是否类似于金属 0 非类似 1 完全
        });
        // 创建网格对象
        const mesh3 = new THREE.Mesh(geometry3, material3);
        mesh3.position.y = 50;
        scene.add(mesh3);

        
        // 创建几何体
        const geometry4 = new THREE.BoxGeometry(10, 10, 10);

        // 复制第一组 UV 坐标作为第二组 UV 坐标
        geometry4.setAttribute('uv2', new THREE.BufferAttribute(geometry4.attributes.uv.array, 2));

        // 创建材质
        const material4 = new THREE.MeshBasicMaterial({
            color: 0xffffff, // 材质颜色
            lightMap: baseTexture, // 设置光照贴图
            lightMapIntensity: 1.0 // 光照贴图的强度
        });
        // 创建网格对象
        const mesh4 = new THREE.Mesh(geometry4, material4);
        mesh4.position.y = -50;
        scene.add(mesh4);
        
        // 创建几何体
        const geometry5 = new THREE.BoxGeometry(10, 10, 10);

        // 创建材质
        const material5 = new THREE.MeshBasicMaterial({
            color: 0x00ff00,
            specularMap: baseTexture, // 高光纹理无效
            wireframe: true,
        });
        // 创建网格对象
        const mesh5 = new THREE.Mesh(geometry5, material5);
        mesh5.position.x = 100;
        scene.add(mesh5);

        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        scene.add(ambientLight);

        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        directionalLight.position.set(10, 10, 10);
        directionalLight.castShadow = true;  // 启用阴影投射
        scene.add(directionalLight);

        // 创建 OrbitControls
        const controls = new OrbitControls(camera, renderer.domElement);
        // 渲染循环
        function animate() {
            requestAnimationFrame(animate);
            controls.update();
            renderer.render(scene, camera);
        }
        animate();
    });
});
</script>
<style lang="scss" scoped="scoped">

    #parkingLot {
        width: 940px;
        height: 940px;
        border: 1px solid #ccc;
        margin: 30px auto;
    }

</style>

结语:由于这个是基础材质,不具备反光属性对其中几个接近无效的属性专门做了描述。对有一些比较难的属性做了立方体示例。