在Three.js中,EXRExporter
API通常用于将场景导出为EXR(OpenEXR)格式的图像。下面是对其入参、出参、方法和属性的详细解释:
-
入参(输入参数):
- scene(场景):要导出的Three.js场景对象。
- camera(相机):用于渲染场景的相机对象。
- options(选项):一个包含导出选项的对象,用于配置导出的行为。这些选项可能包括渲染分辨率、是否包含深度信息等。
-
出参(输出参数):
- EXR文件:导出的EXR格式图像文件。这是通过调用
export
方法并提供正确的入参生成的。
- EXR文件:导出的EXR格式图像文件。这是通过调用
-
方法:
export(scene, camera, options)
:这是主要的方法,用于执行导出操作。它接受三个参数:场景、相机和选项,并返回导出的EXR文件。
-
属性:
- (可能的属性)
- precision(精度):指定导出的EXR文件的精度级别。
- depth (boolean):指定是否导出深度信息。
- resizedWidth(调整后的宽度):指定导出图像的调整后的宽度(如果有的话)。
- resizedHeight(调整后的高度):指定导出图像的调整后的高度(如果有的话)。
- (可能的属性)
在Three.js中,要使用EXRExporter
API,你需要按照以下步骤进行调用:
- 创建一个
EXRExporter
实例:
在你的JavaScript代码中,首先需要创建一个EXRExporter
实例。你可以像这样实例化它:
var exporter = new THREE.EXRExporter();
-
准备场景和相机:
确保你已经创建了要导出的场景对象和相机对象,并将它们准备好传递给导出方法。 -
配置选项(可选):
如果需要,你可以配置导出选项。例如,你可以设置导出的图像分辨率、是否包含深度信息等。将选项对象传递给导出方法。 -
调用导出方法:
调用export
方法,将场景、相机和选项传递给它。该方法将返回导出的EXR文件。你可以将其保存到本地文件或使用它进行其他操作。
// 示例导出调用
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 准备场景和相机...
// 可选:配置导出选项
var options = {
depth: true, // 包含深度信息
resizedWidth: 1024, // 调整后的宽度
resizedHeight: 768 // 调整后的高度
};
// 调用导出方法
var exportedEXR = exporter.export(scene, camera, options);
// 保存导出的EXR文件或进行其他操作
完成源码
以下是给每行代码添加注释后的HTML代码:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - exporter - exr</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - exporter - exr
</div>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js", // 导入Three.js
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three'; // 导入Three.js的全部模块
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // 导入OrbitControls
import { EXRExporter, ZIP_COMPRESSION, ZIPS_COMPRESSION, NO_COMPRESSION } from 'three/addons/exporters/EXRExporter.js'; // 导入EXRExporter和相关常量
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'; // 导入RGBELoader
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; // 导入GUI库
let scene, camera, renderer, exporter, mesh, controls, renderTarget, dataTexture;
const params = { // 定义参数对象
target: 'pmrem', // 目标,默认为'pmrem'
type: 'HalfFloatType', // 类型,默认为'HalfFloatType'
compression: 'ZIP', // 压缩方式,默认为'ZIP'
export: exportFile // 导出文件的回调函数
};
init(); // 初始化
animate(); // 开始动画
function init() { // 初始化函数
renderer = new THREE.WebGLRenderer( { antialias: true } ); // 创建渲染器
renderer.setPixelRatio( window.devicePixelRatio ); // 设置像素比
renderer.setSize( window.innerWidth, window.innerHeight ); // 设置大小
document.body.appendChild( renderer.domElement ); // 将渲染器添加到页面中
//
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 100 ); // 创建相机
camera.position.set( 10, 0, 0 ); // 设置相机位置
scene = new THREE.Scene(); // 创建场景
exporter = new EXRExporter(); // 创建EXRExporter实例
const rgbeloader = new RGBELoader(); // 创建RGBELoader实例
//
const pmremGenerator = new THREE.PMREMGenerator( renderer ); // 创建PMREMGenerator实例
pmremGenerator.compileEquirectangularShader(); // 编译着色器
rgbeloader.load( 'textures/equirectangular/san_giuseppe_bridge_2k.hdr', function ( texture ) { // 加载HDR贴图
texture.mapping = THREE.EquirectangularReflectionMapping;
renderTarget = pmremGenerator.fromEquirectangular( texture ); // 从HDR贴图生成PMREM贴图
scene.background = renderTarget.texture; // 设置场景背景
} );
createDataTexture(); // 创建数据贴图
//
controls = new OrbitControls( camera, renderer.domElement ); // 创建轨道控制器
controls.enableDamping = true; // 启用阻尼
controls.rotateSpeed = - 0.25; // negative, to track mouse pointer
//
window.addEventListener( 'resize', onWindowResize ); // 监听窗口大小变化
const gui = new GUI(); // 创建GUI
const input = gui.addFolder( 'Input' ); // 创建输入文件夹
input.add( params, 'target' ).options( [ 'pmrem', 'data-texture' ] ).onChange( swapScene ); // 添加目标选择框,并监听变化
const options = gui.addFolder( 'Output Options' ); // 创建输出选项文件夹
options.add( params, 'type' ).options( [ 'FloatType', 'HalfFloatType' ] ); // 添加类型选择框
options.add( params, 'compression' ).options( [ 'ZIP', 'ZIPS', 'NONE' ] ); // 添加压缩方式选择框
gui.add( params, 'export' ).name( 'Export EXR' ); // 添加导出按钮
gui.open(); // 打开GUI
}
function onWindowResize() { // 窗口大小变化处理函数
camera.aspect = window.innerWidth / window.innerHeight; // 更新相机宽高比
camera.updateProjectionMatrix(); // 更新相机投影矩阵
renderer.setSize( window.innerWidth, window.innerHeight ); // 更新渲染器大小
}
function animate() { // 动画函数
requestAnimationFrame( animate ); // 请求动画帧
controls.update(); // 更新轨道控制器
renderer.render( scene, camera ); // 渲染场景
}
function createDataTexture() { // 创建数据贴图函数
const normal = new THREE.Vector3(); // 创建法线向量
const coord = new THREE.Vector2(); // 创建坐标向量
const size = 800, radius = 320, factor = Math.PI * 0.5 / radius; // 设置参数
const data = new Float32Array( 4 * size * size ); // 创建数据数组
for ( let i = 0; i < size; i ++ ) {
for ( let j = 0; j < size; j ++ ) {
const idx = i * size * 4 + j * 4;
coord.set( j, i ).subScalar( size / 2 );
if ( coord.length() < radius )
normal.set(
Math.sin( coord.x * factor ),
Math.sin( coord.y * factor ),
Math.cos( coord.x * factor )
);
else
normal.set( 0, 0, 1 );
data[ idx + 0 ] = .5 + .5 * normal.x; // 存储数据
data[ idx + 1 ] = .5 + .5 * normal.y;
data[ idx + 2 ] = .5 + .5 * normal.z;
data[ idx + 3 ] = 1.;
}
}
dataTexture = new THREE.DataTexture( data, size, size, THREE.RGBAFormat, THREE.FloatType ); // 创建数据贴图
dataTexture.needsUpdate = true; // 标记贴图需要更新
const material = new THREE.MeshBasicMaterial( { map: dataTexture } ); // 创建材质
const quad = new THREE.PlaneGeometry( 50, 50 ); // 创建平面几何体
mesh = new THREE.Mesh( quad, material ); // 创建网格
mesh.visible = false; // 设置不可见
scene.add( mesh ); // 添加到场景中
}
function swapScene() { // 切换场景函数
if ( params.target == 'pmrem' ) { // 如果目标为PMREM
camera.position.set( 10, 0, 0 ); // 设置相机位置
controls.enabled = true; // 启用轨道控制器
scene.background = renderTarget.texture; // 设置场景背景为PMREM贴图
mesh.visible = false; // 隐藏数据贴图
} else {
camera.position.set( 0, 0, 70 ); // 设置相机位置
controls.enabled = false; // 禁用轨道控制器
scene.background = new THREE.Color( 0, 0, 0 ); // 设置场景背景为黑色
mesh.visible = true; // 显示数据贴图
}
}
function exportFile() { // 导出文件函数
let result, exportType, exportCompression;
if ( params.type == 'HalfFloatType' ) // 判断类型
exportType = THREE.HalfFloatType;
else
exportType = THREE.FloatType;
if ( params.compression == 'ZIP' ) // 判断压缩方式
exportCompression = ZIP_COMPRESSION;
else if ( params.compression == 'ZIPS' )
exportCompression = ZIPS_COMPRESSION;
else
exportCompression = NO_COMPRESSION;
if ( params.target == 'pmrem' ) // 判断导出目标
result = exporter.parse( renderer, renderTarget, { type: exportType, compression: exportCompression } );
else
result = exporter.parse( dataTexture, { type: exportType, compression: exportCompression } );
saveArrayBuffer( result, params.target + '.exr' ); // 保存文件
}
function saveArrayBuffer( buffer, filename ) { // 保存数组缓冲区函数
const blob = new Blob( [ buffer ], { type: 'image/x-exr' } ); // 创建Blob对象
const link = document.createElement( 'a' ); // 创建链接元素
link.href = URL.createObjectURL( blob ); // 设置链接地址
link.download = filename; // 设置下载文件名
link.click(); // 模拟点击链接
}
</script>
</body>
</html>