Skip to content

景深效果 - DepthOfField

引擎实现的景深效果规定了距离相机最近、最远阈值,在相机和最近距离范围内的物体都为清晰的;而一旦超出了最近距离,物体随距离增加会呈现越来越模糊的效果。直到最远达到最大模糊程度。

ts
//初始化引擎
await Engine3D.init();

Engine3D.setting.render.postProcessing.depthOfView.near = 150;
Engine3D.setting.render.postProcessing.depthOfView.far = 300;
Engine3D.setting.render.postProcessing.depthOfView.pixelOffset = 1;

// 添加 DepthOfFieldPost
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(DepthOfFieldPost); //景深效果。

//开始渲染
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
Engine3D.startRenderView(view);
//初始化引擎
await Engine3D.init();

Engine3D.setting.render.postProcessing.depthOfView.near = 150;
Engine3D.setting.render.postProcessing.depthOfView.far = 300;
Engine3D.setting.render.postProcessing.depthOfView.pixelOffset = 1;

// 添加 DepthOfFieldPost
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(DepthOfFieldPost); //景深效果。

//开始渲染
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
Engine3D.startRenderView(view);

Engine3D.setting.render.postProcessing.depthOfView 配置参数。

参数类型描述
nearnumber设定低于该距离的物体将不会被模糊处理。
farnumber设定高于该距离的物体将会得到最大程度的模糊,[near,far]之间的对象将会使用[0,1]之间线性插值过的系数做模糊处理。
pixelOffsetnumber模糊效果像素扩散距离。


WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

<
ts
import { DepthOfFieldPost, DirectLight, Engine3D, PostProcessingComponent, View3D, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, SSR_IS_Kernel, CameraUtil, webGPUContext, AtmosphericComponent } from '@orillusion/core'
import * as dat from 'dat.gui'

export class Sample_DepthOfView {
    lightObj: Object3D
    scene: Scene3D
    constructor() {}

    async run() {
        Engine3D.setting.shadow.enable = true
        Engine3D.setting.shadow.shadowBound = 100
        await Engine3D.init({
            canvasConfig: {
                devicePixelRatio: 1
            }
        })

        this.scene = new Scene3D()
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6

        let camera = CameraUtil.createCamera3DObject(this.scene)
        camera.perspective(60, webGPUContext.aspect, 1, 5000.0)
        let ctrl = camera.object3D.addComponent(HoverCameraController)
        ctrl.setCamera(100, -15, 150)

        await this.initScene(this.scene)

        let view = new View3D()
        view.scene = this.scene
        view.camera = camera
        Engine3D.startRenderView(view)

        let postProcessing = this.scene.addComponent(PostProcessingComponent)
        let DOFPost = postProcessing.addPost(DepthOfFieldPost)
        DOFPost.near = 0
        DOFPost.far = 150
        DOFPost.pixelOffset = 2

        let GUIHelp = new dat.GUI()
        GUIHelp.addFolder('Depth of Field')
        GUIHelp.add(DOFPost, 'near', 0, 100, 1)
        GUIHelp.add(DOFPost, 'far', 150, 300, 1)
    }

    async initScene(scene: Scene3D) {
        /******** light *******/
        {
            this.lightObj = new Object3D()
            this.lightObj.rotationX = 15
            this.lightObj.rotationY = 110
            this.lightObj.rotationZ = 0
            let lc = this.lightObj.addComponent(DirectLight)
            lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355)
            lc.castShadow = true
            lc.intensity = 10
            scene.addChild(this.lightObj)
        }

        // load a test gltf model
        let minimalObj = await Engine3D.res.loadGltf('https://cdn.orillusion.com/PBR/ToyCar/ToyCar.gltf')
        minimalObj.scaleX = minimalObj.scaleY = minimalObj.scaleZ = 800
        scene.addChild(minimalObj)

        this.createPlane(scene)
        return true
    }

    private createPlane(scene: Scene3D) {
        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.grayTexture
        mat.normalMap = Engine3D.res.normalTexture
        mat.aoMap = Engine3D.res.whiteTexture
        mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 10.0, 0.0, 1)
        mat.emissiveMap = Engine3D.res.blackTexture
        mat.roughness = 0.1
        mat.roughness_max = 0.1
        mat.metallic = 0.0

        {
            let debugGeo = new PlaneGeometry(2000, 2000)
            let obj: Object3D = new Object3D()
            let mr = obj.addComponent(MeshRenderer)
            mr.material = mat
            mr.geometry = debugGeo
            scene.addChild(obj)
        }

        {
            let sphereGeometry = new SphereGeometry(10, 50, 50)
            let obj: Object3D = new Object3D()
            let mr = obj.addComponent(MeshRenderer)
            mr.material = mat
            mr.geometry = sphereGeometry
            obj.x = 30
            obj.y = 10
            scene.addChild(obj)
        }

        {
            let seeds = SSR_IS_Kernel.createSeeds()
            let sphereGeometry = new SphereGeometry(2, 50, 50)
            for (let i = 0; i < seeds.length; i++) {
                let pt = seeds[i]
                let obj: Object3D = new Object3D()
                let mr = obj.addComponent(MeshRenderer)
                mr.material = mat
                mr.geometry = sphereGeometry

                obj.y = pt.z
                obj.x = pt.x
                obj.z = pt.y
                scene.addChild(obj)
            }
        }
    }
}

new Sample_DepthOfView().run()
import { DepthOfFieldPost, DirectLight, Engine3D, PostProcessingComponent, View3D, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, SSR_IS_Kernel, CameraUtil, webGPUContext, AtmosphericComponent } from '@orillusion/core'
import * as dat from 'dat.gui'

export class Sample_DepthOfView {
    lightObj: Object3D
    scene: Scene3D
    constructor() {}

    async run() {
        Engine3D.setting.shadow.enable = true
        Engine3D.setting.shadow.shadowBound = 100
        await Engine3D.init({
            canvasConfig: {
                devicePixelRatio: 1
            }
        })

        this.scene = new Scene3D()
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6

        let camera = CameraUtil.createCamera3DObject(this.scene)
        camera.perspective(60, webGPUContext.aspect, 1, 5000.0)
        let ctrl = camera.object3D.addComponent(HoverCameraController)
        ctrl.setCamera(100, -15, 150)

        await this.initScene(this.scene)

        let view = new View3D()
        view.scene = this.scene
        view.camera = camera
        Engine3D.startRenderView(view)

        let postProcessing = this.scene.addComponent(PostProcessingComponent)
        let DOFPost = postProcessing.addPost(DepthOfFieldPost)
        DOFPost.near = 0
        DOFPost.far = 150
        DOFPost.pixelOffset = 2

        let GUIHelp = new dat.GUI()
        GUIHelp.addFolder('Depth of Field')
        GUIHelp.add(DOFPost, 'near', 0, 100, 1)
        GUIHelp.add(DOFPost, 'far', 150, 300, 1)
    }

    async initScene(scene: Scene3D) {
        /******** light *******/
        {
            this.lightObj = new Object3D()
            this.lightObj.rotationX = 15
            this.lightObj.rotationY = 110
            this.lightObj.rotationZ = 0
            let lc = this.lightObj.addComponent(DirectLight)
            lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355)
            lc.castShadow = true
            lc.intensity = 10
            scene.addChild(this.lightObj)
        }

        // load a test gltf model
        let minimalObj = await Engine3D.res.loadGltf('https://cdn.orillusion.com/PBR/ToyCar/ToyCar.gltf')
        minimalObj.scaleX = minimalObj.scaleY = minimalObj.scaleZ = 800
        scene.addChild(minimalObj)

        this.createPlane(scene)
        return true
    }

    private createPlane(scene: Scene3D) {
        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.grayTexture
        mat.normalMap = Engine3D.res.normalTexture
        mat.aoMap = Engine3D.res.whiteTexture
        mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 10.0, 0.0, 1)
        mat.emissiveMap = Engine3D.res.blackTexture
        mat.roughness = 0.1
        mat.roughness_max = 0.1
        mat.metallic = 0.0

        {
            let debugGeo = new PlaneGeometry(2000, 2000)
            let obj: Object3D = new Object3D()
            let mr = obj.addComponent(MeshRenderer)
            mr.material = mat
            mr.geometry = debugGeo
            scene.addChild(obj)
        }

        {
            let sphereGeometry = new SphereGeometry(10, 50, 50)
            let obj: Object3D = new Object3D()
            let mr = obj.addComponent(MeshRenderer)
            mr.material = mat
            mr.geometry = sphereGeometry
            obj.x = 30
            obj.y = 10
            scene.addChild(obj)
        }

        {
            let seeds = SSR_IS_Kernel.createSeeds()
            let sphereGeometry = new SphereGeometry(2, 50, 50)
            for (let i = 0; i < seeds.length; i++) {
                let pt = seeds[i]
                let obj: Object3D = new Object3D()
                let mr = obj.addComponent(MeshRenderer)
                mr.material = mat
                mr.geometry = sphereGeometry

                obj.y = pt.z
                obj.x = pt.x
                obj.z = pt.y
                scene.addChild(obj)
            }
        }
    }
}

new Sample_DepthOfView().run()