当前位置: 首页 > article >正文

【Three.js基础学习】21.Realistic rendering

前言

课程回顾

        渲染器

        1.色调映射

            值意在将高动态范围](HDR)值转换为低动态范围(LDR)

            Three.is中的色调映射实际上会伪造将LDR转换为HDR的过程,即使颜色不是HDR,

            结果会产生非常逼真的渲染效果

            THREE .NoToneMapping (default)  无色调映射

            THREE.LinearToneMapping         线性色调映射

            THREE.ReinhardToneMapping      

            THREE.CineonToneMapping

            THREE.ACESFilmicToneMapping

        2.色调映射曝光

            放了多少光

            toneMappingExposure

        3.抗锯齿 Antialiasing(混叠) 取决于像素比

            讨论两种方法

            1.超级采样(SSAA)或全屏采样(FSAA)

            我们把分辨率提高到实际分辨率以外。当调整为正常尺寸时,每个像素颜色将自动从渲染的4个像素中平均出来

            简单但对性能不好

            2.多采样(MSAA)

            由最新的GPU自动执行

            将检查被渲染像素的邻居。如果是几何图形的边缘,将将其颜色与邻居的颜色混合。

            仅适用于几何边缘

   

        平行光投射阴影

        环境地图不能投射阴影我们需要添加一盏与环境图的照明大致相符的光,并用它投射阴影

        阴影

            开启

            renderer.shadowMap.enabled = true ; // 开启阴影

            renderer.shadowMap.type = THREE.PCFSoftShadowMap // 设置阴影类型

            设置光辅助相机

            平行光开启阴影-》设置相机更行矩阵

            updateWorldMatrix

            在物体模型上开启阴影 ,并且接受阴影

        纹理和颜色空间

            使用木橱柜磨损长度/纹理在模型下方创建一个8x8平面

            使用castle brick broken 06/纹理在模型后面创建一个8x8的平面

        纹理看起来奇怪的白色,这是由于“颜色空间”颜色空间是一种根据人眼敏感度优化颜色存储方式的方法。

            主要涉及应该被看到的纹理(在我们的例子中,bricksColorTexture)

        需要改变颜色空间 , 哪些图gl,arm属于线性,diff属于sRGB ,需要变成线性

        为什么不对模型使用颜色空间?

            原因是GLTF已经包含这些颜色信息

       

        在颜色纹理上更改颜色空间

        floorColorTexture.colorSpace = THREE.SRGBColorSpace

        换成汉堡包

        降低环境强度发现很奇怪,有线的条纹

        原因:由于计算时精确原因,阴影痤疮可能发生在光滑,平坦的表面上;表面是否在阴影中 ;汉堡包正在给自己蒙上一层阴影

        解决:1. 在平行光上,正常量偏移,让汉堡包变大或变小,这样表面没有深度,不会接受阴影

        bias:

        normalBias:

        贴图强度会降低阴影的可见性

一、代码

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import GUI from 'lil-gui'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
import { floor } from 'three/examples/jsm/nodes/nodes'


/**
 * Loaders
 */
const gltfLoader = new GLTFLoader()
const rgbeLoader = new RGBELoader()

/*
    TextureLoad
 */
const textureLoader = new THREE.TextureLoader()

/**
 * Base
 */
// Debug
const gui = new GUI()
const global = {}

// Canvas
const canvas = document.querySelector('canvas.webgl')

// Scene
const scene = new THREE.Scene()

/**
 * Update all materials
 */
const updateAllMaterials = () =>
{
    scene.traverse((child) =>
    {
        if(child.isMesh && child.material.isMeshStandardMaterial)
        {
            child.material.envMapIntensity = global.envMapIntensity
            child.castShadow = true // 在物体上开启阴影
            child.receiveShadow = true
        }
    })
}

/**
 * Environment map
 */
// Global intensity
global.envMapIntensity = 1
gui
    .add(global, 'envMapIntensity')
    .min(0)
    .max(10)
    .step(0.001)
    .onChange(updateAllMaterials)

// HDR (RGBE) equirectangular
rgbeLoader.load('/environmentMaps/0/2k.hdr', (environmentMap) =>
{
    environmentMap.mapping = THREE.EquirectangularReflectionMapping

    scene.background = environmentMap
    scene.environment = environmentMap
})

/* 
    Directional Light
*/
const directionalLight = new THREE.DirectionalLight('#ffffff',2)
directionalLight.position.set(-4,6.5,2.5)

scene.add(directionalLight)

gui.add(directionalLight,'intensity').min(0).max(10).step(0.001).name('lightIntensity') // 光强度
gui.add(directionalLight.position,'x').min(-10).max(10).step(0.001).name('lightX') // 光x轴
gui.add(directionalLight.position,'y').min(-10).max(10).step(0.001).name('lightY')
gui.add(directionalLight.position,'z').min(-10).max(10).step(0.001).name('lightZ')

// Shadows
directionalLight.castShadow = true
directionalLight.shadow.camera.far = 15
directionalLight.shadow.normalBias = 0.027
directionalLight.shadow.bias = -0.004
directionalLight.shadow.mapSize.set(512,512) // 数值越大 阴影越清晰
gui.add(directionalLight,'castShadow')

gui.add(directionalLight.shadow,'normalBias').min(-0.05).max(0.05).step(0.001)
gui.add(directionalLight.shadow,'bias').min(-0.05).max(0.05).step(0.001)

// Helper  光辅助相机
// const directionalLightCameraHelper = new THREE.CameraHelper(directionalLight.shadow.camera)
// scene.add(directionalLightCameraHelper)

// target
directionalLight.target.position.set(0,4,0)  //若只是设置这个不生效 , 
directionalLight.target.updateWorldMatrix()  // 加上这个 渲染时,更新矩阵模型 就可以

/**
 * Models
 */
// Helmet
// gltfLoader.load(
//     '/models/FlightHelmet/glTF/FlightHelmet.gltf',
//     (gltf) =>
//     {
//         gltf.scene.scale.set(10, 10, 10)
//         scene.add(gltf.scene)

//         updateAllMaterials()
//     }
// )
// 汉堡包
gltfLoader.load(
    '/models/hamburger.glb',
    (gltf) =>
    {
        gltf.scene.scale.set(0.4, 0.4, 0.4)
        gltf.scene.position.set(0,2.5,0)
        scene.add(gltf.scene)

        updateAllMaterials()
    }
)

/* 
    floor
*/
const floorColorTexture = textureLoader.load('/textures/wood_cabinet_worn_long/wood_cabinet_worn_long_diff_1k.jpg')
const floorColorNormalTexture = textureLoader.load('/textures/wood_cabinet_worn_long/wood_cabinet_worn_long_nor_gl_1k.jpg')
const floorColorAORoughnessMetalnessTexture = textureLoader.load('/textures/wood_cabinet_worn_long/wood_cabinet_worn_long_arm_1k.jpg')
floorColorTexture.colorSpace = THREE.SRGBColorSpace

const floorPlaneInWooden = new THREE.Mesh(
    new THREE.PlaneGeometry(8,8),
    new THREE.MeshStandardMaterial({
        map:floorColorTexture,
        normalMap:floorColorNormalTexture, // 法线贴图 ,保持细节
        aoMap:floorColorAORoughnessMetalnessTexture, // AO贴图,金属度和粗糙度
        roughnessMap:floorColorAORoughnessMetalnessTexture,
        metalnessMap:floorColorAORoughnessMetalnessTexture,
        // color:new THREE.Color(10, 4, 2)
    })
)
floorPlaneInWooden.rotation.x = - Math.PI * 0.5
scene.add(floorPlaneInWooden)

/* 
    wall
*/
const wallColorTexture = textureLoader.load('/textures/castle_brick_broken_06/castle_brick_broken_06_diff_1k.jpg')
const wallColorNormalTexture = textureLoader.load('/textures/castle_brick_broken_06/castle_brick_broken_06_nor_gl_1k.jpg')
const wallColorAORoughnessMetalnessTexture = textureLoader.load('/textures/castle_brick_broken_06/castle_brick_broken_06_arm_1k.jpg')

wallColorTexture.colorSpace = THREE.SRGBColorSpace

const wallPlaneInWooden = new THREE.Mesh(
    new THREE.PlaneGeometry(8,8),
    new THREE.MeshStandardMaterial({
        map:wallColorTexture,
        normalMap:wallColorNormalTexture, // 法线贴图 ,保持细节
        aoMap:wallColorAORoughnessMetalnessTexture, // AO贴图,金属度和粗糙度
        roughnessMap:wallColorAORoughnessMetalnessTexture,
        metalnessMap:wallColorAORoughnessMetalnessTexture,
        // color:new THREE.Color(10, 4, 2)
    })
)
// wallPlaneInWooden.rotation.x = - Math.PI * 0.5
wallPlaneInWooden.position.y = 4
wallPlaneInWooden.position.z = - 4
scene.add(wallPlaneInWooden)


/**
 * Sizes
 */
const sizes = {
    width: window.innerWidth,
    height: window.innerHeight
}

window.addEventListener('resize', () =>
{
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight

    // Update camera
    camera.aspect = sizes.width / sizes.height
    camera.updateProjectionMatrix()

    // Update renderer
    renderer.setSize(sizes.width, sizes.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})

/**
 * Camera
 */
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
camera.position.set(4, 5, 4)
scene.add(camera)

// Controls
const controls = new OrbitControls(camera, canvas)
controls.target.y = 3.5
controls.enableDamping = true

/**
 * Renderer
 */
const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias:true // 反别名
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
 
// tone mapping
renderer.toneMapping = THREE.ReinhardToneMapping 
renderer.toneMappingExposure = 3

gui.add(renderer,'toneMapping',{
    No:THREE.NoToneMapping,
    Linear:THREE.LinearToneMapping,
    Reinhard:THREE.ReinhardToneMapping,
    Cineon:THREE.CineonToneMapping,
    ACESFimlmic:THREE.ACESFilmicToneMapping,
})
gui.add(renderer,'toneMappingExposure').min(0).max(10).step(0.001)

// Shadows
renderer.shadowMap.enabled = true ; // 开启阴影
renderer.shadowMap.type = THREE.PCFSoftShadowMap // 设置阴影类型

/**
 * Animate
 */
const tick = () =>
{
    // Update controls
    controls.update()

    // Render
    renderer.render(scene, camera)

    // Call tick again on the next frame
    window.requestAnimationFrame(tick)
}

tick()

二、知识点

1.色调映射,抗锯齿     

可以看的在颜色变化的周围,没有想锯齿一样的,而是很平滑

const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias:true // 反别名
})

色调映射:值意在将高动态范围](HDR)值转换为低动态范围(LDR)

            THREE .NoToneMapping (default)  无色调映射

            THREE.LinearToneMapping         线性色调映射

            THREE.ReinhardToneMapping      

            THREE.CineonToneMapping

            THREE.ACESFilmicToneMapping

色调映射曝光

            放了多少光

            toneMappingExposure

抗锯齿 Antialiasing(混叠) 取决于像素比

讨论两种方法

            1.超级采样(SSAA)或全屏采样(FSAA)

            我们把分辨率提高到实际分辨率以外。当调整为正常尺寸时,每个像素颜色将自动从渲染的4个像素中平均出来

            简单但对性能不好

            2.多采样(MSAA) (采用这种)

            由最新的GPU自动执行

            将检查被渲染像素的邻居。如果是几何图形的边缘,将将其颜色与邻居的颜色混合。

            仅适用于几何边缘

2. 平行光投射阴影,阴影

激活灯光投射阴影,开启阴影,物体上开启阴影接受        

renderer.shadowMap.enabled = true ; // 开启阴影
renderer.shadowMap.type = THREE.PCFSoftShadowMap // 设置阴影类型
const updateAllMaterials = () =>
{
    scene.traverse((child) =>
    {
        if(child.isMesh && child.material.isMeshStandardMaterial)
        {
            child.material.envMapIntensity = global.envMapIntensity
            child.castShadow = true // 在物体上开启阴影
            child.receiveShadow = true
        }
    })
}
const directionalLight = new THREE.DirectionalLight('#ffffff',2)
directionalLight.position.set(-4,6.5,2.5)

scene.add(directionalLight)

gui.add(directionalLight,'intensity').min(0).max(10).step(0.001).name('lightIntensity') // 光强度
gui.add(directionalLight.position,'x').min(-10).max(10).step(0.001).name('lightX') // 光x轴
gui.add(directionalLight.position,'y').min(-10).max(10).step(0.001).name('lightY')
gui.add(directionalLight.position,'z').min(-10).max(10).step(0.001).name('lightZ')

// Shadows
directionalLight.castShadow = true
directionalLight.shadow.camera.far = 15
directionalLight.shadow.normalBias = 0.027
directionalLight.shadow.bias = -0.004
directionalLight.shadow.mapSize.set(512,512) // 数值越大 阴影越清晰
gui.add(directionalLight,'castShadow')

3.颜色空间设置

设置之后可以看到原本黄色的墙正常

wallColorTexture.colorSpace = THREE.SRGBColorSpace

floorColorTexture.colorSpace = THREE.SRGBColorSpace

4.不同模型 阴影设置

设置之后对应条纹优化

global.envMapIntensity = 0

 directionalLight.shadow.normalBias = 0.027
 directionalLight.shadow.bias = -0.004

 gui.add(directionalLight.shadow,'normalBias').min(-0.05).max(0.05).step(0.001)
 gui.add(directionalLight.shadow,'bias').min(-0.05).max(0.05).step(0.001)


总结

让显示的效果更好!


http://www.kler.cn/a/387120.html

相关文章:

  • 基于表格滚动截屏(表格全部展开,没有滚动条)
  • go语言中的log 包详解
  • 如何使用IDEA创建Maven/SSM工程?
  • 软件工程的基础和核心理论概念
  • 工业通信协议对比:OPC-UA、Modbus、MQTT、HTTP
  • VCSVerdi:KDB文件的生成和导入
  • css:基础
  • go语言中如何使用 select 语句处理多通道
  • 基于STM32的LCD1602显示Proteus仿真设计(仿真+程序+设计报告+讲解视频)
  • 论软件可靠性设计及其应用
  • Linux: network: ip link M-DOWN的具体含义是什么?
  • 论文阅读--基于MLS点云语义分割和螺栓孔定位的盾构隧道错位检测方法
  • 如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
  • 怎么解决码流多slice场景下的马赛克、绿屏问题?
  • 云原生安全解决方案NeuVector 5.X部署实践
  • 鸿蒙笔记--skills
  • NestJS 项目中如何使用 class-validator 进行数据验证
  • 从认识 VNode VDOM 到实现 mini-vue
  • 【数据结构与算法】第9课—数据结构之二叉树(链式结构)
  • es数据同步(仅供自己参考)
  • 机器学习中的分类:决策树、随机森林及其应用
  • 鸿道Intewell高实时架构:鸿道Intewell-Hyper II 构型
  • c语言宏定义的优缺点及举例说明
  • AscendC从入门到精通系列(二)基于Kernel直调开发AscendC算子
  • Vue禁止打开控制台/前端禁止打开控制台方法/禁用F12/禁用右键
  • 如何设置docker的定时关闭和启动