@volter/blender-engine 0.1.135 → 0.1.137
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/browser/session.py
CHANGED
|
@@ -1216,11 +1216,16 @@ def _depsgraph_placements(frame, depsgraph):
|
|
|
1216
1216
|
continue
|
|
1217
1217
|
if not instance.show_self:
|
|
1218
1218
|
continue
|
|
1219
|
+
# AN UNSUPPORTED PLACEMENT IS LEFT OUT, NAMED ONCE (`warn`): raising here
|
|
1220
|
+
# lost the whole frame, so one odd instance kept the entire scene from
|
|
1221
|
+
# opening. The native exporter skips the same duplis.
|
|
1219
1222
|
if (instance.instance_object is not None and instance.object.data != instance.instance_object.data and
|
|
1220
1223
|
(instance.object.data is None or geometry.get(source.name) != instance.object.data.as_pointer())):
|
|
1221
|
-
|
|
1224
|
+
warn("Depsgraph instances of %r are not drawn: their geometry differs from the exported source" % source.name)
|
|
1225
|
+
continue
|
|
1222
1226
|
if row is None or (source.type == "MESH" and row["mesh"] is None):
|
|
1223
|
-
|
|
1227
|
+
warn("Depsgraph instances of %r are not drawn: the source has no exported geometry" % source.name)
|
|
1228
|
+
continue
|
|
1224
1229
|
if row["mesh"] is None:
|
|
1225
1230
|
if source.type not in ("EMPTY", "CAMERA"):
|
|
1226
1231
|
warn("Depsgraph instance %r of type %s is not drawn" % (source.name, source.type))
|
|
@@ -1228,7 +1233,8 @@ def _depsgraph_placements(frame, depsgraph):
|
|
|
1228
1233
|
owner = instance.parent.original if instance.parent is not None else None
|
|
1229
1234
|
owner_row = by_name.get(owner.name) if owner is not None else None
|
|
1230
1235
|
if owner is not None and owner_row is None:
|
|
1231
|
-
|
|
1236
|
+
warn("Depsgraph instances owned by %r are not drawn: the owner is not exported" % owner.name)
|
|
1237
|
+
continue
|
|
1232
1238
|
persistent = list(instance.persistent_id)
|
|
1233
1239
|
particle_index = persistent[0]
|
|
1234
1240
|
psys = instance.particle_system
|
|
@@ -1687,7 +1693,11 @@ class Session:
|
|
|
1687
1693
|
for row in frame["objects"]:
|
|
1688
1694
|
if not any(m in graphs for m in row["materials"] if m is not None):
|
|
1689
1695
|
continue
|
|
1690
|
-
|
|
1696
|
+
# An instance source from a collection outside the scene is exported
|
|
1697
|
+
# too (`instance_sources`) and shares these graphs; its Object Info
|
|
1698
|
+
# and Particle Info inputs come from the file's own objects. Only
|
|
1699
|
+
# those few rows miss the scene's map.
|
|
1700
|
+
obj = by_name.get(row["name"]) or bpy.data.objects.get(row["name"])
|
|
1691
1701
|
if obj is not None:
|
|
1692
1702
|
row["object_info"] = {
|
|
1693
1703
|
"color": [float(v) for v in obj.color],
|
|
@@ -7,7 +7,7 @@ import {z} from 'zod';
|
|
|
7
7
|
import {applyGraphShader, bindGraphDraw, bindPaletteGraph, borrowGraphDrawBinding, graphProgramKey, graphUvChannels, setGraphViewport} from './blender-graph-material';
|
|
8
8
|
import type {CompiledGraph} from './blender-node-graph';
|
|
9
9
|
import {bindNamedUvChannels} from './blender-texture-samplers';
|
|
10
|
-
import {copyWorldVisibility,worldVisibilityShader,worldVisibilityUniforms} from './blender-world-visibility';
|
|
10
|
+
import {WORLD_VISIBILITY,copyWorldVisibility,worldVisibilityShader,worldVisibilityUniforms} from './blender-world-visibility';
|
|
11
11
|
|
|
12
12
|
const scalar = z.number().finite();
|
|
13
13
|
const color = z.tuple([scalar, scalar, scalar]);
|
|
@@ -195,7 +195,7 @@ export function applyPhysicalMaterial(material: THREE.MeshPhysicalMaterial, inpu
|
|
|
195
195
|
blenderWorldExtinction: {value: new THREE.Vector3()}};
|
|
196
196
|
uniforms.set(material, values);
|
|
197
197
|
const held = values;
|
|
198
|
-
material.customProgramCacheKey = () => `blender-principled-physical-v6${graphProgramKey(material)}`;
|
|
198
|
+
material.customProgramCacheKey = () => `blender-principled-physical-v6${WORLD_VISIBILITY ? '-atlas' : ''}${graphProgramKey(material)}`;
|
|
199
199
|
material.onBeforeRender = (renderer, scene, camera, geometry, object) => {
|
|
200
200
|
bindNamedUvChannels(material, geometry);
|
|
201
201
|
bindGraphDraw(material, geometry, renderer, scene, camera, object, graphShadow);
|
|
@@ -213,12 +213,16 @@ export function applyPhysicalMaterial(material: THREE.MeshPhysicalMaterial, inpu
|
|
|
213
213
|
.map(i => (i <= 3 ? `#ifndef USE_UV${i}\nattribute vec2 uv${i};\n#endif` : `attribute vec2 uv${i};`))
|
|
214
214
|
.join('\n') + '\n' + shader.vertexShader;
|
|
215
215
|
Object.assign(shader.uniforms, held);
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
'#include <
|
|
216
|
+
// The sky-light atlas exists in the shader only while it is on: its three
|
|
217
|
+
// samplers would count against every material's sixteen (WORLD_VISIBILITY).
|
|
218
|
+
if (WORLD_VISIBILITY) {
|
|
219
|
+
worldVisibilityUniforms(material,shader.uniforms);
|
|
220
|
+
shader.vertexShader='varying vec3 blenderWorldPosition;\n'+shader.vertexShader;
|
|
221
|
+
shader.vertexShader=shader.vertexShader.replace('#include <worldpos_vertex>',
|
|
222
|
+
'#include <worldpos_vertex>\n#if defined(USE_ENVMAP) || defined(USE_SHADOWMAP) || defined(USE_TRANSMISSION)\nblenderWorldPosition=worldPosition.xyz;\n#else\nblenderWorldPosition=(modelMatrix*vec4(transformed,1.)).xyz;\n#endif');
|
|
223
|
+
shader.fragmentShader=shader.fragmentShader.replace('#include <envmap_physical_pars_fragment>',
|
|
224
|
+
'#include <envmap_physical_pars_fragment>\n'+worldVisibilityShader);
|
|
225
|
+
}
|
|
222
226
|
shader.fragmentShader = `uniform float blenderCoatIor;
|
|
223
227
|
uniform vec3 blenderWorldExtinction;
|
|
224
228
|
vec3 blenderInfiniteTransmission() { return vec3(
|
|
@@ -263,11 +267,13 @@ export function applyPhysicalMaterial(material: THREE.MeshPhysicalMaterial, inpu
|
|
|
263
267
|
.replace('rectAreaLight = rectAreaLights[ i ];',
|
|
264
268
|
'rectAreaLight = rectAreaLights[ i ]; rectAreaLight.color *= exp(-blenderWorldExtinction * length(rectAreaLight.position-geometryPosition));')
|
|
265
269
|
.replace('getAmbientLightIrradiance( ambientLightColor )', 'getAmbientLightIrradiance( ambientLightColor ) * blenderInfiniteTransmission()');
|
|
266
|
-
const
|
|
270
|
+
const visible = WORLD_VISIBILITY ? THREE.ShaderChunk.lights_fragment_maps
|
|
267
271
|
.replace('getIBLIrradiance( geometryNormal )',
|
|
268
272
|
'blenderWorldIrradiance( geometryNormal, getIBLIrradiance( geometryNormal ) )')
|
|
269
273
|
.replaceAll(/(getIBL(?:Radiance|AnisotropyRadiance)\([^;]+\))/g,
|
|
270
274
|
'$1 * blenderWorldReflectionVisibility(geometryViewDir,geometryNormal,material.roughness)')
|
|
275
|
+
: THREE.ShaderChunk.lights_fragment_maps;
|
|
276
|
+
const environment = visible
|
|
271
277
|
.replaceAll(/(getIBL(?:Irradiance|Radiance|AnisotropyRadiance)\([^;]+\))/g, '$1 * blenderInfiniteTransmission()');
|
|
272
278
|
shader.fragmentShader = shader.fragmentShader.replace('#include <lights_physical_fragment>', physical)
|
|
273
279
|
.replace('#include <lights_fragment_begin>', lighting)
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
worldSchema,
|
|
28
28
|
} from './blender-runtime-lighting';
|
|
29
29
|
import { fitModelDirectionalShadow, visibleShadowReceivers } from './blender-runtime-shadows';
|
|
30
|
-
import {BlenderWorldVisibility,bindWorldVisibility} from './blender-world-visibility';
|
|
30
|
+
import {BlenderWorldVisibility,WORLD_VISIBILITY,bindWorldVisibility} from './blender-world-visibility';
|
|
31
31
|
import { volumeMesh, volumeSchema } from './blender-runtime-volume';
|
|
32
32
|
import { applyPhysicalMaterial, applyWorldExtinction, physicalMaterialSchema } from './blender-physical-material';
|
|
33
33
|
import { prepareGraphGeometry, setMaterialGraph } from './blender-graph-material';
|
|
@@ -799,7 +799,7 @@ export class BlenderRuntimeView {
|
|
|
799
799
|
* (`blender-workbench-material.ts`) over their viewport display. */
|
|
800
800
|
private workbench = false;
|
|
801
801
|
private readonly workbenchMaterials = new Map<string, THREE.Material>();
|
|
802
|
-
private readonly fallback = new THREE.MeshPhysicalMaterial({ color: 0xb9bec6, roughness: 0.72, side: THREE.DoubleSide });
|
|
802
|
+
private readonly fallback = new THREE.MeshPhysicalMaterial({ color: 0xb9bec6, roughness: 0.72, side: THREE.DoubleSide, shadowSide: THREE.BackSide });
|
|
803
803
|
/** Base Color images, by image name -- ONE texture per image however many
|
|
804
804
|
* materials read it, and the cache OWNS it: a material points at one and
|
|
805
805
|
* never disposes it. Held with the size and revision the resident bytes
|
|
@@ -1429,13 +1429,15 @@ export class BlenderRuntimeView {
|
|
|
1429
1429
|
// objects. Fit shadows for that draw, rather than the camera's pose
|
|
1430
1430
|
// when Rendered shading was first entered. Captures use this path too.
|
|
1431
1431
|
if (this.rendered) this.applyShadows(true, camera);
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
const
|
|
1436
|
-
|
|
1432
|
+
if (WORLD_VISIBILITY) {
|
|
1433
|
+
this.worldVisibility.sync(this.objects.values(),this.world.lightingTexture(),this.root,this.rendered);
|
|
1434
|
+
for(const material of [...this.materials.values(),this.fallback])bindWorldVisibility(material,this.worldVisibility);
|
|
1435
|
+
for(const object of this.objects.values()) {
|
|
1436
|
+
const mesh=object as THREE.Mesh;if(!mesh.isMesh)continue;
|
|
1437
|
+
for(const material of Array.isArray(mesh.material)?mesh.material:[mesh.material])bindWorldVisibility(material,this.worldVisibility);
|
|
1438
|
+
}
|
|
1439
|
+
if(options?.renderer)this.worldVisibility.prepare(options.renderer);
|
|
1437
1440
|
}
|
|
1438
|
-
if(options?.renderer)this.worldVisibility.prepare(options.renderer);
|
|
1439
1441
|
const opaqueDone = performance.now();
|
|
1440
1442
|
const motion = this.motionGeometry.prepare(camera, !this.rendered && (this.mode ?? this.frame?.mode) === 'OBJECT' &&
|
|
1441
1443
|
options?.interactive === true, options?.height ?? 0);
|
|
@@ -1995,7 +1997,11 @@ export class BlenderRuntimeView {
|
|
|
1995
1997
|
for (const [id, data] of Object.entries(next.materials)) {
|
|
1996
1998
|
// Cycles intersects and shades both faces, including an arcade viewed
|
|
1997
1999
|
// from underneath. Three's front-face default drops those surfaces.
|
|
1998
|
-
|
|
2000
|
+
// The shadow map keeps the back faces a front-faced material draws
|
|
2001
|
+
// there: a two-sided depth pass puts every lit face into its own map, and
|
|
2002
|
+
// the normal offset cannot hold that off at grazing light.
|
|
2003
|
+
const material = this.materials.get(id) ??
|
|
2004
|
+
new THREE.MeshPhysicalMaterial({ side: THREE.DoubleSide, shadowSide: THREE.BackSide });
|
|
1999
2005
|
material.name = data.name;
|
|
2000
2006
|
// A LINKED BASE COLOUR REPLACES THE SOCKET'S VALUE, it does not multiply
|
|
2001
2007
|
// it. Python's `_reduce` fills `color` from the Base Color socket's
|
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
* directional quadrature, not indirect light transport. */
|
|
5
5
|
import * as THREE from 'three';
|
|
6
6
|
|
|
7
|
+
/** SKY-LIGHT OCCLUSION IS OFF IN EVERY VIEW, and compiled out of every material. Its
|
|
8
|
+
* sixteen 512-square tiles each span the whole scene, so a 360 m level gets
|
|
9
|
+
* about a metre per texel, and each lookup is one nearest texel answering
|
|
10
|
+
* yes or no. Faceted surfaces then occlude their own sky at random pixels --
|
|
11
|
+
* static on every polygon in Rendered and Play -- and narrow specular lobes,
|
|
12
|
+
* dominated by a few of the sixteen directions, plausibly flash as the camera
|
|
13
|
+
* moves. It measured right in a closed room a few metres across. Turn it back
|
|
14
|
+
* on once its lookups are filtered and its resolution follows the scene's size
|
|
15
|
+
* (docs/BLENDER-RENDERING-PARITY.md lists the rest). Off, the view neither
|
|
16
|
+
* syncs nor draws the atlas (`blender-runtime-view.ts`), and physical
|
|
17
|
+
* materials declare none of its samplers (`blender-physical-material.ts`):
|
|
18
|
+
* three of them counted against a material's sixteen even while unused. */
|
|
19
|
+
export const WORLD_VISIBILITY = false;
|
|
20
|
+
|
|
7
21
|
const SAMPLE_COUNT=16, TILES=4, TILE_SIZE=512;
|
|
8
22
|
type Segment={mesh:THREE.Mesh; geometry:THREE.BufferGeometry; position:THREE.BufferAttribute|THREE.InterleavedBufferAttribute;
|
|
9
23
|
index:THREE.BufferAttribute|null; positionVersion:number; indexVersion:number; start:number; count:number;
|