threejs hdr白皮书 0 特殊的玻璃和金属高反材质详细解析

[复制链接]
查看: 1897   回复: 0     threejs白皮书

232

主题

232

帖子

1279

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1279
2022-10-13 16:34:02   显示全部楼层   阅读模式  
微信截图_20221014180902.png

1.png

软件激活码 6677
软件下载地址:

最新的软件下载地址
https://www.xiefansq.cn/forum.php?mod=forumdisplay&fid=2


本篇是在这个csdn的这个文章基础上做的拓展补充哈:点击跳转


本期我设计的DEMO直观感觉



1.hdr的科普

HDR全称High-Dynamic Range(高动态光照渲染),通过HDR,显示器或相机可以很好的表现超出其亮度范围的图像,也可以简单理解为HDR能大幅提高画面细节的明暗对比度。直白点讲,HDR是指一个图像中最亮处和最暗处之间的比值,能够让图像明亮的地方更亮,而黑色的地方更黑暗深邃。

HDR由两部分组成,动态曝光控制和光晕效果。先说动态曝光控制,通常,显示器能够显示R、G、B分量在[0,255]之间的像素值。而256个不同的亮度级别显然不能表示自然界中光线的亮度情况。举个例子,太阳的亮度是白炽灯亮度的几千倍或者被漫反射照亮的室内亮度的几万倍,这远远超出了显示器的亮度表示能力。HDR技术所要解决的问题就是在有限的亮度范围内表示出宽广的亮度范围。原理类似于照相机的曝光功能,通过算法调整光线亮度,将光线从高动态范围映射到低动态范围,从而得到得到令人信服的光照效果。

HDR的另一部分是光晕效果。人从暗处走到光亮的地方,瞳孔由于来不及收缩,眼睛会自己眯起来,以保护视网膜上的感光细胞。HDR通过对原始图像进行调整,可以模拟这种人眼自动适应光线变化的生理反应,产生类似于光晕的效果。

图像经HDR处理后的理想结果是亮处足够耀眼,暗处能够分辨物体的轮廓与深度,而非原图的一团漆黑。

2.环境纹理(全景)
在Three中,环境纹理的实现一方面借助hdr材质的加载,另一方面借助于环境纹理实现的算法,其主要包括两种模式,一种是球面环境纹理,另一种是立方体环境纹理模式。两种实现方式原理上与地图学中的投影相似。

1)球形全景是将球形的经度和纬度坐标,直接到水平和垂直坐标的一格,这个网格的高度大约宽的两倍。因此从赤道到两极,横向拉伸不断加剧,南北两个极点被拉伸成了扁平的网格在整个上部和下部边缘。球形全景可以现实整个水平和竖直的360全景。
1.png

2)立方体全景是将全景图分成了前后左右上下六个面,浏览的时候将六个面结合成一个密闭空间来现实整个水平和竖直的360全景。

也可以这样

2.png

3.png

4.png

3.CubeTextureLoader加载立方体环境纹理
加载CubeTexture的一个类。 内部使用ImageLoader来加载文件。px/nx/py/ny/pz/nz:该六个配置项分别表示盒模型六个贴面在坐标系中不同方向的贴图地址,如下图所示。手动输入贴图的URL地址,可设置盒模型样式。

1.jpg

4.hdr加载的三种写法以及其中优劣

1)通过rgbe加载器 ,加载最高质量的hdr

优点:这个方案是加载的hdr质量最高,然后其表现的色彩细节最为细腻

缺点:hdr文件的为16位通道,体积较大,不利于我们项目的轻量化,用jpg体积更加,也可以达到不错的效果

代码书写方法
 
import { RGBELoader } from "./plugin/three.js-r130/examples/jsm/loaders/RGBELoader.js";//rgbe加载器
     const rgbeLoader = new RGBELoader();
        rgbeLoader.loadAsync("img/hdr/hdr-32.hdr").then((texture) => {
        texture.mapping = THREE.EquirectangularReflectionMapping;
        //将加载的材质texture设置给背景和环境
        // scene.background = texture;
        // scene.environment = texture;
        })

2)通过CubeTextureLoader,六面图的方案载入hdr

优点:对比单张的hdr,最大优势他没有天空以及地面拉伸,对比方案一整体的图片体积也更加小
1.png

2.png

优点:一个是贴图拉扯到,两级仔细看细节尤其是做展馆项目就很不推荐使用,这个球mesh来装填我们的hdr环境

缺点:就是要六张图,切图真的很烦,而且还要根据一定顺序 旋转 排好。。。

代码书写方式:
  var path = './img/cubeMap/1/';
            var format = '.jpg';
            const cubeMap1 = new THREE.CubeTextureLoader().load( [
                            path + '天空0000' + format, path + '天空0001' + format,
                            path + '天空0002' + format, path + '天空0003' + format,
                            path + '天空0004' + format, path + '天空0005' + format
            ] );

3)通过超级基础的texLoader,载入jpg格式的hdr

优点:体积小,也是除了展馆以外。。。的项目最推荐一种载入公共hdr方式

缺点:跟第一种载入.hdr问题一样有拉升,作为background,没有六面图

书写方式:
      //载入jpg hdr的方案 第三种方案
        var texLoader = new THREE.TextureLoader()
        const jpgTexPath= "img/jpg/";
        var format = '.jpg';
                        function addMaterial(nam){
                                const tex =texLoader.load( jpgTexPath +nam+ format);
                                return(tex)
                        }

       var HdrMap = addMaterial("www-xiefansq-com_2K_01");                
        HdrMap.encoding = THREE.sRGBEncoding;
        HdrMap.mapping = THREE.EquirectangularRefractionMapping
总结:三种的hdr都有其存在意义,面对不同项目我们可以搭配使用,但是最最推荐,以及最最通用还是第三种方案。。。做展馆的时候可以采用3+2方案,3设置为environment的公共映射,2方案作为background实际展示

5.两种高反特性
1)cubemap的
THREE.CubeReflectionMapping //反射映射(默认值)
THREE.CubeRefractionMapping //折射映射

2通用map的
THREE.EquirectangularReflectionMapping//反射映射(默认值)
THREE.EquirectangularRefractionMapping //折射映射

一定要注意他们的区别,别看字母就差那么一点点

3.png

那好家伙最后的,实际应用感觉差差老多了

总结而言就是
折射映射,我们主要用来做玻璃材质的,玻璃看穿透过背景时候,他会扭曲背景。。。。
而反射映射,设置的hdr,他是专门针对金属的,是无法实现穿透扭曲效果

直观截图

4.png

这里公共的 scene.environment= HdrMap 是反射映射模式
所以场上所有的都是反射的模型,此时如果不特殊设置,玻璃材质就是打死也写不出来的

然后对于玻璃这个方块,单独写了一个折射映射的hdr,并且指定要书写的材质里面,于是神器的hdr就出现了

以下攻略源码感兴趣,可以阅读学习
<!DOCTYPE html>
<html>
        <head>
                <meta charset="utf-8">
                <title>threejs HDR白皮书</title>
    </head>
        <body>
        <script type="module">

        import { OrbitControls } from './plugin/three.js-r130/examples/jsm/controls/OrbitControls.js';
        import * as THREE from './plugin/three.js-r130/build/three.module.js';
        import { GLTFLoader } from './plugin/three.js-r130/examples/jsm/loaders/GLTFLoader.js';
        import { RGBELoader } from "./plugin/three.js-r130/examples/jsm/loaders/RGBELoader.js";//rgbe加载器

        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000 );
        const renderer = new THREE.WebGLRenderer({ antialias: true } );
        renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.outputEncoding = THREE.sRGBEncoding//srg颜色
    //  renderer.toneMappingExposure = 1
        document.body.appendChild( renderer.domElement );

        camera.position.set(-16,15,20)

         //载入hdr的方案 第一种方案
        const rgbeLoader = new RGBELoader();
        rgbeLoader.loadAsync("img/hdr/hdr-32.hdr").then((texture) => {
        texture.mapping = THREE.EquirectangularReflectionMapping;
        //将加载的材质texture设置给背景和环境
        // scene.background = texture;
        // scene.environment = texture;
        })


       

        //载入cubemap hdr的方案 第二种方案
                        var path = './img/cubeMap/1/';
            var format = '.jpg';
            const cubeMap1 = new THREE.CubeTextureLoader().load( [
                            path + '天空0000' + format, path + '天空0001' + format,
                            path + '天空0002' + format, path + '天空0003' + format,
                            path + '天空0004' + format, path + '天空0005' + format
            ] );
            // cubeMap1.mapping =THREE.CubeRefractionMapping
            cubeMap1.mapping = THREE.CubeRefractionMapping;
    


        //载入jpg hdr的方案 第三种方案
        var texLoader = new THREE.TextureLoader()
        const jpgTexPath= "img/jpg/";
        var format = '.jpg';
                        function addMaterial(nam){
                                const tex =texLoader.load( jpgTexPath +nam+ format);
                                return(tex)
                        }

        var HdrMap = addMaterial("www-xiefansq-com_2K_01");                
            HdrMap.encoding = THREE.sRGBEncoding;
                HdrMap.mapping = THREE.EquirectangularRefractionMapping

        scene.environment= HdrMap ;   
        scene.background = cubeMap1;
        // scene.environment =rgbeLoader ;

        const geometry = new THREE.BoxGeometry( 1, 1, 1 );
        const material = new THREE.MeshPhysicalMaterial( {
            color: 0xffffff,
               // transmission:0.8,
            // reflectivity:1,
            metalness:1,
            roughness:0,

            // Thickness:1.3,
            // transparent: true,
        } );
        const cube = new THREE.Mesh( geometry, material );
        scene.add( cube );
        cube.scale.set(3,3,3)
        cube.position.set(-4.63,4.4,0)

        const cube1=cube.clone()//克隆一个方向
        const CubeMaterial = new THREE.MeshPhysicalMaterial( {
            color: 0xffffff,
            transmission:1,
            reflectivity:0.3,
            metalness:1,
            roughness:0.01,
            // Thickness:0.35,
            envMap: cubeMap1,
            refractionRatio: 0.98,
            ior:1.8,
            transparent: true,
            opacity:0.9,
            // dithering :true
        } );
        cube1.material=CubeMaterial
        scene.add( cube1 );
        cube1.position.set(0,4.4,0)

        const geometry1 = new THREE.PlaneGeometry( 20, 20 );
        const material1 = new THREE.MeshPhysicalMaterial( {
            color: 0xffffff, 
         
            side: THREE.DoubleSide
        } );
        const plane = new THREE.Mesh( geometry1, material1 );
        scene.add( plane );
        plane.rotation.x=-90/180 *Math.PI;

        const pointLight = new THREE.PointLight( 0xffffff, 1, 100 );
        pointLight.position.set(12,12.5,14.9)
        scene.add( pointLight );

        const light1 = new THREE.AmbientLight( 0xffffff,0.1); // soft white light
        scene.add( light1 );
       
        

        var controls = new OrbitControls(camera, renderer.domElement);//设置相机可以操作的权限
        controls.target=new THREE.Vector3( 0, 4.4, 0 );
        function animate() {
               
                requestAnimationFrame( animate );
                renderer.render( scene, camera );
                controls.update()
            }
            animate();
            
        </script>
    </body>
    </html>













六面图 threejs 代码生成器.zip免费

2022-10-14 18:17上传, 417.2 KB, 下载次数: 234

下载

threejs六面图适配代码生成器1.3.exe免费

2022-10-14 20:37上传, 756 KB, 下载次数: 220

下载

回复

使用道具 举报

您需要登录后才可以回帖   登录 立即注册

高级模式

南通谢凡软件科技有限公司