You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
18 KiB
254 lines
18 KiB
2 years ago
|
<!DOCTYPE html><html lang="ru"><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="/manual/resources/lesson.css">
|
||
|
<link rel="stylesheet" href="/manual/resources/lang.css">
|
||
|
<!-- Import maps polyfill -->
|
||
|
<!-- Remove this when import maps will be widely supported -->
|
||
|
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
|
||
|
|
||
|
<script type="importmap">
|
||
|
{
|
||
|
"imports": {
|
||
|
"three": "../../build/three.module.js"
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="container">
|
||
|
<div class="lesson-title">
|
||
|
<h1>Туман</h1>
|
||
|
</div>
|
||
|
<div class="lesson">
|
||
|
<div class="lesson-main">
|
||
|
<p>Эта статья является частью серии статей о three.js. Первая статья - <a href="fundamentals.html">основы Three.js</a>.
|
||
|
Если вы еще не читали их, и вы новичок в three.js, возможно, вы захотите начать с них.
|
||
|
Если вы еще не читали о камерах, вы можете начать с <a href="cameras.html">этой статьи</a>.</p>
|
||
|
<p>Туман в 3D-движке - это, как правило, способ затухания до определенного цвета в зависимости от расстояния до камеры.
|
||
|
В three.js вы добавляете туман, создавая объект <a href="/docs/#api/en/scenes/Fog"><code class="notranslate" translate="no">Fog</code></a> или <a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a> и устанавливая его в свойстве сцены
|
||
|
<a href="/docs/#api/en/scenes/Scene#fog"><code class="notranslate" translate="no">fog</code></a>.</p>
|
||
|
<p><a href="/docs/#api/en/scenes/Fog"><code class="notranslate" translate="no">Fog</code></a> позволяет выбирать <code class="notranslate" translate="no">near</code> и <code class="notranslate" translate="no">far</code> настройки, которые находятся на расстоянии от камеры.
|
||
|
Все, что <code class="notranslate" translate="no">near</code> не подвержено влиянию тумана.
|
||
|
Все, что <code class="notranslate" translate="no">far</code> - это цвет тумана. Части между <code class="notranslate" translate="no">near</code> и <code class="notranslate" translate="no">far</code> переходят от их материального цвета к цвету тумана. </p>
|
||
|
<p>Есть также <a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a>, который растет экспоненциально с расстоянием от камеры.</p>
|
||
|
<p>Чтобы использовать любой тип тумана, вы создаете его и назначаете его сцене, как в </p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
|
||
|
{
|
||
|
const color = 0xFFFFFF; // white
|
||
|
const near = 10;
|
||
|
const far = 100;
|
||
|
scene.fog = new THREE.Fog(color, near, far);
|
||
|
}
|
||
|
</pre>
|
||
|
<p>или для <a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a> это будет</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
|
||
|
{
|
||
|
const color = 0xFFFFFF;
|
||
|
const density = 0.1;
|
||
|
scene.fog = new THREE.FogExp2(color, density);
|
||
|
}
|
||
|
</pre>
|
||
|
<p><a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a> ближе к реальности, но <a href="/docs/#api/en/scenes/Fog"><code class="notranslate" translate="no">Fog</code></a> используется чаще, поскольку он позволяет вам выбрать место для нанесения тумана,
|
||
|
чтобы вы могли решить показать чистую сцену на определенном расстоянии, а затем исчезновение до некоторого цвета за этим расстоянием. </p>
|
||
|
<div class="spread">
|
||
|
<div>
|
||
|
<div data-diagram="fog" style="height: 300px;"></div>
|
||
|
<div class="code">THREE.Fog</div>
|
||
|
</div>
|
||
|
<div>
|
||
|
<div data-diagram="fogExp2" style="height: 300px;"></div>
|
||
|
<div class="code">THREE.FogExp2</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<p>Важно отметить, что туман применяется к <em>вещам, которые отображаются</em>.
|
||
|
Это часть расчета каждого пикселя цвета объекта.
|
||
|
Это означает, что если вы хотите, чтобы ваша сцена стала блеклой, вам нужно установить туман <strong>и</strong> цвет фона на один и тот же цвет.
|
||
|
Цвет фона устанавливается с помощью свойства <a href="/docs/#api/en/scenes/Scene#background"><code class="notranslate" translate="no">scene.background</code></a>. Чтобы выбрать цвет фона, вы прикрепляете к нему <a href="/docs/#api/en/math/Color"><code class="notranslate" translate="no">THREE.Color</code></a>. Например </p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">scene.background = new THREE.Color('#F00'); // red
|
||
|
</pre>
|
||
|
<div class="spread">
|
||
|
<div>
|
||
|
<div data-diagram="fogBlueBackgroundRed" style="height: 300px;" class="border"></div>
|
||
|
<div class="code">fog blue, background red</div>
|
||
|
</div>
|
||
|
<div>
|
||
|
<div data-diagram="fogBlueBackgroundBlue" style="height: 300px;" class="border"></div>
|
||
|
<div class="code">fog blue, background blue</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<p>Вот один из наших предыдущих примеров с добавленным туманом.
|
||
|
Единственное добавление - сразу после настройки сцены мы добавляем туман и устанавливаем цвет фона сцены </p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
|
||
|
|
||
|
+{
|
||
|
+ const near = 1;
|
||
|
+ const far = 2;
|
||
|
+ const color = 'lightblue';
|
||
|
+ scene.fog = new THREE.Fog(color, near, far);
|
||
|
+ scene.background = new THREE.Color(color);
|
||
|
+}
|
||
|
</pre>
|
||
|
<p>В приведенном ниже примере <code class="notranslate" translate="no">near</code> камеры равен 0,1, а <code class="notranslate" translate="no">far</code> - 5. Камера находится в точке <code class="notranslate" translate="no">z = 2</code>.
|
||
|
Кубики имеют размер 1 и имеют значение <code class="notranslate" translate="no">z = 0</code>.
|
||
|
Это означает, что при настройке тумана <code class="notranslate" translate="no">near = 1</code> и <code class="notranslate" translate="no">far = 2</code> кубики исчезнут прямо вокруг их центра. </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/fog.html"></iframe></div>
|
||
|
<a class="threejs_center" href="/manual/examples/fog.html" target="_blank">нажмите здесь, чтобы открыть в отдельном окне</a>
|
||
|
</div>
|
||
|
|
||
|
<p></p>
|
||
|
<p>Давайте добавим интерфейс, чтобы мы могли настроить туман. Мы снова будем использовать
|
||
|
<a href="https://github.com/georgealways/lil-gui">lil-gui</a>. lil-gui принимает объект и свойство и автоматически создает интерфейс для этого типа свойства.
|
||
|
Мы могли бы просто позволить ему манипулировать свойствами <code class="notranslate" translate="no">near</code> и <code class="notranslate" translate="no">far</code> тумана, но недопустимо иметь <code class="notranslate" translate="no">near</code> больше, чем <code class="notranslate" translate="no">far</code>, поэтому давайте создадим помощник,
|
||
|
чтобы lil-gui мог манипулировать свойством <code class="notranslate" translate="no">near</code> и <code class="notranslate" translate="no">far</code>,
|
||
|
но мы убедимся, что <code class="notranslate" translate="no">near</code> меньше или равно <code class="notranslate" translate="no">far</code> и <code class="notranslate" translate="no">far</code> больше или равно <code class="notranslate" translate="no">near</code>. </p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// We use this class to pass to lil-gui
|
||
|
// so when it manipulates near or far
|
||
|
// near is never > far and far is never < near
|
||
|
class FogGUIHelper {
|
||
|
constructor(fog) {
|
||
|
this.fog = fog;
|
||
|
}
|
||
|
get near() {
|
||
|
return this.fog.near;
|
||
|
}
|
||
|
set near(v) {
|
||
|
this.fog.near = v;
|
||
|
this.fog.far = Math.max(this.fog.far, v);
|
||
|
}
|
||
|
get far() {
|
||
|
return this.fog.far;
|
||
|
}
|
||
|
set far(v) {
|
||
|
this.fog.far = v;
|
||
|
this.fog.near = Math.min(this.fog.near, v);
|
||
|
}
|
||
|
}
|
||
|
</pre>
|
||
|
<p>Затем мы можем добавить это так</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
|
||
|
const near = 1;
|
||
|
const far = 2;
|
||
|
const color = 'lightblue';
|
||
|
scene.fog = new THREE.Fog(color, near, far);
|
||
|
scene.background = new THREE.Color(color);
|
||
|
+
|
||
|
+ const fogGUIHelper = new FogGUIHelper(scene.fog);
|
||
|
+ gui.add(fogGUIHelper, 'near', near, far).listen();
|
||
|
+ gui.add(fogGUIHelper, 'far', near, far).listen();
|
||
|
}
|
||
|
</pre>
|
||
|
<p>Параметры <code class="notranslate" translate="no">near</code> и <code class="notranslate" translate="no">far</code> задают минимальные и максимальные значения для регулировки тумана. Они устанавливаются при настройке камеры. </p>
|
||
|
<p><code class="notranslate" translate="no">.Listen ()</code> в конце последних 2 строк указывает lil-gui <em>прослушивать</em>
|
||
|
изменения. Таким образом, когда мы меняем <code class="notranslate" translate="no">near</code> на <code class="notranslate" translate="no">far</code> или мы меняем <code class="notranslate" translate="no">far</code> на <code class="notranslate" translate="no">near</code> lil-gui обновит интерфейс другого свойства для нас. </p>
|
||
|
<p>Также было бы неплохо иметь возможность изменить цвет тумана, но, как было упомянуто выше, нам нужно синхронизировать цвет тумана и цвет фона.
|
||
|
Итак, давайте добавим еще одно <em>виртуальное</em> свойство в наш помощник, который будет устанавливать оба цвета, когда lil-gui манипулирует им. </p>
|
||
|
<p>lil-gui может манипулировать цветами 4 способами, как шестнадцатеричная строка из 6 цифр CSS (например: <code class="notranslate" translate="no"># 112233</code>).
|
||
|
Как тон, насыщенность, яркость объекта (например: <code class="notranslate" translate="no">{h: 60, s: 1, v:}</code>).
|
||
|
Как массив RGB (например: <code class="notranslate" translate="no">[255, 128, 64]</code>). Или как массив RGBA (например: <code class="notranslate" translate="no">[127, 200, 75, 0.3]</code>). </p>
|
||
|
<p>Для нашей цели проще всего использовать шестнадцатеричную версию, поскольку таким образом lil-gui манипулирует только одним значением.
|
||
|
К счастью, <a href="/docs/#api/en/math/Color"><code class="notranslate" translate="no">THREE.Color</code></a> как метод <a href="/docs/#api/en/math/Color#getHexString"><code class="notranslate" translate="no">getHexString</code></a>
|
||
|
который мы используем, чтобы легко получить такую cтроку - нам просто нужно добавить <code class="notranslate" translate="no">«#»</code> вперед. </p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// We use this class to pass to lil-gui
|
||
|
// so when it manipulates near or far
|
||
|
// near is never > far and far is never < near
|
||
|
+// Also when lil-gui manipulates color we'll
|
||
|
+// update both the fog and background colors.
|
||
|
class FogGUIHelper {
|
||
|
* constructor(fog, backgroundColor) {
|
||
|
this.fog = fog;
|
||
|
+ this.backgroundColor = backgroundColor;
|
||
|
}
|
||
|
get near() {
|
||
|
return this.fog.near;
|
||
|
}
|
||
|
set near(v) {
|
||
|
this.fog.near = v;
|
||
|
this.fog.far = Math.max(this.fog.far, v);
|
||
|
}
|
||
|
get far() {
|
||
|
return this.fog.far;
|
||
|
}
|
||
|
set far(v) {
|
||
|
this.fog.far = v;
|
||
|
this.fog.near = Math.min(this.fog.near, v);
|
||
|
}
|
||
|
+ get color() {
|
||
|
+ return `#${this.fog.color.getHexString()}`;
|
||
|
+ }
|
||
|
+ set color(hexString) {
|
||
|
+ this.fog.color.set(hexString);
|
||
|
+ this.backgroundColor.set(hexString);
|
||
|
+ }
|
||
|
}
|
||
|
</pre>
|
||
|
<p>Затем мы вызываем <code class="notranslate" translate="no">gui.addColor</code>, чтобы добавить интерфейс цвета для виртуального свойства нашего помощника.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
|
||
|
const near = 1;
|
||
|
const far = 2;
|
||
|
const color = 'lightblue';
|
||
|
scene.fog = new THREE.Fog(color, near, far);
|
||
|
scene.background = new THREE.Color(color);
|
||
|
|
||
|
* const fogGUIHelper = new FogGUIHelper(scene.fog, scene.background);
|
||
|
gui.add(fogGUIHelper, 'near', near, far).listen();
|
||
|
gui.add(fogGUIHelper, 'far', near, far).listen();
|
||
|
+ gui.addColor(fogGUIHelper, 'color');
|
||
|
}
|
||
|
</pre>
|
||
|
<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/fog-gui.html"></iframe></div>
|
||
|
<a class="threejs_center" href="/manual/examples/fog-gui.html" target="_blank">нажмите здесь, чтобы открыть в отдельном окне</a>
|
||
|
</div>
|
||
|
|
||
|
<p></p>
|
||
|
<p>Вы можете видеть <code class="notranslate" translate="no">near</code> до 1,9, а <code class="notranslate" translate="no">far</code> до 2,0 дает очень резкий переход между незатуманенным и полностью затуманенным.
|
||
|
где <code class="notranslate" translate="no">near</code> = 1,1 и <code class="notranslate" translate="no">far</code> = 2,9 должны быть примерно самыми гладкими, учитывая, что наши кубики вращаются на 2 единицы от камеры. </p>
|
||
|
<p>И последнее: на материале существует логическое свойство <a href="/docs/#api/en/materials/Material#fog"><code class="notranslate" translate="no">fog</code></a>,
|
||
|
определяющее, влияет ли туман на объекты, созданные с этим материалом.
|
||
|
По умолчанию это <code class="notranslate" translate="no">true</code> для большинства материалов. В качестве примера того, почему вы можете захотеть отключить туман, представьте,
|
||
|
что вы делаете 3D-симулятор автомобиля с видом с места водителя или из кабины.
|
||
|
Вы, вероятно, хотите, чтобы тумана не было внутри, если смотреть изнутри автомобиля. </p>
|
||
|
<p>Лучшим примером может быть дом и густой туман вне дома. Допустим, туман установлен на расстоянии 2 метра ( near = 2) и полностью затуманен на 4 метра ( far = 4).
|
||
|
Комнаты длиннее 2 метров, а дом, вероятно, длиннее 4 метров, поэтому вам необходимо установить материалы для внутренней части дома,
|
||
|
чтобы не было тумана, в противном случае, если вы будете стоять внутри дома, глядя на стену в дальнем конце комнаты, она будет в тумане. </p>
|
||
|
<div class="spread">
|
||
|
<div>
|
||
|
<div data-diagram="fogHouseAll" style="height: 300px;" class="border"></div>
|
||
|
<div class="code">fog: true, all</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<p>Обратите внимание, что на стены и потолок в дальнем конце комнаты распространяется туман. Отключив туман для материалов дома, мы можем решить эту проблему. </p>
|
||
|
<div class="spread">
|
||
|
<div>
|
||
|
<div data-diagram="fogHouseInsideNoFog" style="height: 300px;" class="border"></div>
|
||
|
<div class="code">fog: true, only outside materials</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<p><canvas id="c"></canvas></p>
|
||
|
<script type="module" src="../resources/threejs-fog.js"></script>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<script src="/manual/resources/prettify.js"></script>
|
||
|
<script src="/manual/resources/lesson.js"></script>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
</body></html>
|