You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
earthquake_3d_viewer_front/three/manual/zh/rendertargets.html

162 lines
7.7 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html><html lang="zh"><head>
<meta charset="utf-8">
<title>渲染目标</title>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@threejs">
<meta name="twitter:title" content="Three.js 渲染目标">
<meta property="og:image" content="https://threejs.org/files/share.png">
<link rel="shortcut icon" href="../../files/favicon_white.ico" media="(prefers-color-scheme: dark)">
<link rel="shortcut icon" href="../../files/favicon.ico" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="../resources/lesson.css">
<link rel="stylesheet" href="../resources/lang.css">
<script type="importmap">
{
"imports": {
"three": "../../build/three.module.js"
}
}
</script>
<link rel="stylesheet" href="/manual/zh/lang.css">
</head>
<body>
<div class="container">
<div class="lesson-title">
<h1>渲染目标</h1>
</div>
<div class="lesson">
<div class="lesson-main">
<p>在three.js中渲染目标大体上指的是可以被渲染的纹理。当它被渲染之后你可以像使用其他纹理一样使用它。</p>
<p>让我们举个简单的例子。我们将从<a href="responsive.html">the article on responsiveness</a>开始。</p>
<p>渲染到渲染目标基本上跟通常的渲染一样。首先我们创建一个 <a href="/docs/#api/zh/renderers/WebGLRenderTarget"><code class="notranslate" translate="no">WebGLRenderTarget</code></a></p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const rtWidth = 512;
const rtHeight = 512;
const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);
</pre>
<p>然后我们需要一个 <a href="/docs/#api/zh/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> 和一个 <a href="/docs/#api/zh/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a></p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const rtFov = 75;
const rtAspect = rtWidth / rtHeight;
const rtNear = 0.1;
const rtFar = 5;
const rtCamera = new THREE.PerspectiveCamera(rtFov, rtAspect, rtNear, rtFar);
rtCamera.position.z = 2;
const rtScene = new THREE.Scene();
rtScene.background = new THREE.Color('red');
</pre>
<p>注意我们设置长宽比(aspect)是相对渲染目标而言的,不是画布(canvas)。
正确的长宽比取决于我们要渲染的对象。在本例我们要将渲染目标的纹理用在方块的一个面基于方块的面我们设置长宽比为1.0。</p>
<p>我们将需要的东西添加到场景中。在本例我们使用灯光和三个方块<a href="responsive.html">from the previous article</a></p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
* rtScene.add(light);
}
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
function makeInstance(geometry, color, x) {
const material = new THREE.MeshPhongMaterial({color});
const cube = new THREE.Mesh(geometry, material);
* rtScene.add(cube);
cube.position.x = x;
return cube;
}
*const rtCubes = [
makeInstance(geometry, 0x44aa88, 0),
makeInstance(geometry, 0x8844aa, -2),
makeInstance(geometry, 0xaa8844, 2),
];
</pre>
<p>在上个例子中的 <a href="/docs/#api/zh/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a><a href="/docs/#api/zh/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> 保持不变,我们将在画布中继续使用它们,只需要添加渲染的物体。</p>
<p>让我们添加使用了渲染目标纹理的方块。</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const material = new THREE.MeshPhongMaterial({
map: renderTarget.texture,
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
</pre>
<p>现在在渲染的时候,我们首先将渲染目标的场景(rtScene),渲染到渲染目标(注:这里有点绕,需要结合代码理解)。</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
time *= 0.001;
...
// rotate all the cubes in the render target scene
rtCubes.forEach((cube, ndx) =&gt; {
const speed = 1 + ndx * .1;
const rot = time * speed;
cube.rotation.x = rot;
cube.rotation.y = rot;
});
// draw render target scene to render target
renderer.setRenderTarget(renderTarget);
renderer.render(rtScene, rtCamera);
renderer.setRenderTarget(null);
</pre>
<p>然后我们在画布中,渲染使用了渲染目标纹理的方块的场景。</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no"> // rotate the cube in the scene
cube.rotation.x = time;
cube.rotation.y = time * 1.1;
// render the scene to the canvas
renderer.render(scene, camera);
</pre>
<p>就是这样啦</p>
<p></p><div translate="no" class="threejs_example_container notranslate">
<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/render-target.html"></iframe></div>
<a class="threejs_center" href="/manual/examples/render-target.html" target="_blank">点击此处在新标签页中打开</a>
</div>
<p></p>
<p>方块是红色的,这是因为我们设置了 <code class="notranslate" translate="no">rtScene</code><code class="notranslate" translate="no">background</code> 为红色,所以渲染目标的纹理所处的背景为红色。</p>
<p>渲染目标可以用在各种各样的物体上。<a href="shadows.html">Shadows</a>用了渲染目标,<a href="picking.html">Picking can use a render target</a>,多种效果<a href="post-processing.html">post processing effects</a>需要用到渲染目标。
渲染汽车的后视镜或者3D场景中的监控实时画面都可能用到渲染目标。</p>
<p>关于 <a href="/docs/#api/zh/renderers/WebGLRenderTarget"><code class="notranslate" translate="no">WebGLRenderTarget</code></a> 的笔记。</p>
<ul>
<li><p>默认情况下 <a href="/docs/#api/zh/renderers/WebGLRenderTarget"><code class="notranslate" translate="no">WebGLRenderTarget</code></a> 会创建两个纹理。 颜色纹理和深度/模版纹理。如果你不需要深度或者模版纹理,你可以通过可选设置取消创建。例如:</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no"> const rt = new THREE.WebGLRenderTarget(width, height, {
depthBuffer: false,
stencilBuffer: false,
});
</pre>
</li>
<li><p>你可能需要改变渲染目标的尺寸</p>
<p>在上面的例子我们创建了固定尺寸512X512的渲染目标。对于像后处理你通常需要创建跟画布一样尺寸的渲染目标。在我们的代码中意味着当我们改变画布的尺寸会同时更新渲染目标尺寸和渲染目标中正在使用的摄像机。例如</p>
<pre class="prettyprint showlinemods notranslate notranslate" translate="no">function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
+ renderTarget.setSize(canvas.width, canvas.height);
+ rtCamera.aspect = camera.aspect;
+ rtCamera.updateProjectionMatrix();
}
</pre></li>
</ul>
</div>
</div>
</div>
<script src="../resources/prettify.js"></script>
<script src="../resources/lesson.js"></script>
</body></html>