@volter/blender-engine 0.1.136 → 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.
@@ -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
- raise NotImplementedError("Depsgraph instance geometry differs from its native source: %s" % source.name)
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
- raise NotImplementedError("Depsgraph instance source has no native exported geometry: %s" % source.name)
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
- raise NotImplementedError("Depsgraph instance owner is not exported: %s" % owner.name)
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
- obj = by_name.get(row["name"])
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
- worldVisibilityUniforms(material,shader.uniforms);
217
- shader.vertexShader='varying vec3 blenderWorldPosition;\n'+shader.vertexShader;
218
- shader.vertexShader=shader.vertexShader.replace('#include <worldpos_vertex>',
219
- '#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');
220
- shader.fragmentShader=shader.fragmentShader.replace('#include <envmap_physical_pars_fragment>',
221
- '#include <envmap_physical_pars_fragment>\n'+worldVisibilityShader);
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 environment = THREE.ShaderChunk.lights_fragment_maps
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';
@@ -58,16 +58,6 @@ const SAVED_SHADING = {
58
58
  MATERIAL: 'preview',
59
59
  RENDERED: 'rendered',
60
60
  } as const;
61
- /** SKY-LIGHT OCCLUSION (`blender-world-visibility.ts`) IS OFF IN EVERY VIEW. Its
62
- * sixteen 512-square tiles each span the whole scene, so a 360 m level gets
63
- * about a metre per texel, and each lookup is one nearest texel answering
64
- * yes or no. Faceted surfaces then occlude their own sky at random pixels --
65
- * static on every polygon in Rendered and Play -- and narrow specular lobes,
66
- * dominated by a few of the sixteen directions, plausibly flash as the camera
67
- * moves. It measured right in a closed room a few metres across. Turn it back
68
- * on once its lookups are filtered and its resolution follows the scene's size
69
- * (docs/BLENDER-RENDERING-PARITY.md lists the rest). */
70
- const WORLD_VISIBILITY = false;
71
61
  const scalar = z.number().finite();
72
62
  const point = z.tuple([scalar, scalar, scalar]);
73
63
  const edge = z.tuple([z.number().int().nonnegative(), z.number().int().nonnegative()]);
@@ -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;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@volter/blender-engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "GPL-3.0-or-later",
5
- "version": "0.1.136",
5
+ "version": "0.1.137",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },