feat: immerse the portfolio in a chromatic synthwave night
Carry rose, violet, coral, electric blue and cyan through the interface, road, terrain, signs and atmosphere. Add a Blender-authored paint edition and matching runtime fallback captures. Interpolate atmospheric color on a small sky lattice and enrich existing speed effects without another rendering pass. Preserve approved copy, project media, metadata, navigation contracts and adaptive audio. Verified with typecheck, client/SSR builds, validated prerendering, artifact and transfer checks, responsive Chrome interaction, fallback checks and Intel-backed performance sampling.
This commit is contained in:
12
assets/blender/chromatic/README.md
Normal file
12
assets/blender/chromatic/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Chromatic grand tourer
|
||||
|
||||
Original paint edition of the approved expressway coachwork at `43e5103`, descended from the evolution model at `c9ac36e`. No external models or textures are used.
|
||||
|
||||
- `nightdrive-chromatic.blend`: isolated **Chromatic Nightdrive** scene with editable geometry, rose and violet layered paint, sapphire glass, champagne wheel machining, and look-development lights.
|
||||
- `author-chromatic.py`: appends the approved expressway source and changes its materials in an isolated scene. Set `__file__` to this script when executing in Blender. It writes only the chromatic library.
|
||||
- `export-chromatic.py`: run with the chromatic scene loaded. Evaluates modifiers and batches by material and wheel, retaining four independently rotatable wheel parents. Writes the GLB and SHA-256 provenance.
|
||||
- `nightdrive-chromatic.asset.json`: source lineage and export statistics.
|
||||
|
||||
Geometry is unchanged: 31,288 triangles and 19 material batches. Runtime studio reflections supply cool edge light and a rose rim over the exported enamel. Runtime emissive fill remains subtle; the body is lit paint, not an illuminated surface. The earlier Blender sources and exports are preserved.
|
||||
|
||||
The chromatic Static-mode JPEGs are direct captures of this portfolio’s runtime world at desktop and phone sizes. They contain no project evidence or invented imagery.
|
||||
43
assets/blender/chromatic/author-chromatic.py
Normal file
43
assets/blender/chromatic/author-chromatic.py
Normal file
@@ -0,0 +1,43 @@
|
||||
"""Append the approved model as an isolated, editable chromatic paint edition.
|
||||
Run in Blender with __file__ set to this script. Open projects are never saved.
|
||||
"""
|
||||
import bpy
|
||||
from pathlib import Path
|
||||
root_path = Path(__file__).resolve().parents[3]
|
||||
source = root_path / 'assets/blender/expressway/nightdrive-expressway.blend'
|
||||
with bpy.data.libraries.load(str(source), link=False) as (available, loaded):
|
||||
loaded.scenes = ['Midnight Expressway']
|
||||
scene = loaded.scenes[0]
|
||||
scene.name = 'Chromatic Nightdrive'
|
||||
bpy.context.window.scene = scene
|
||||
materials = {m.name.split('.')[0]: m for o in scene.objects if o.type in {'MESH','CURVE'} for m in o.data.materials}
|
||||
# Linear RGB: candy-rose enamel, violet shoulders, champagne machining,
|
||||
# sapphire glass and dark plum mechanical recesses. Geometry stays approved.
|
||||
for name, color, metallic, roughness in [
|
||||
('M_Body_Gunmetal', (0.46, 0.023, 0.145, 1), 0.68, 0.24),
|
||||
('M_Body_Haunch', (0.36, 0.035, 0.38, 1), 0.72, 0.22),
|
||||
('M_Lower_Graphite', (0.029, 0.01, 0.047, 1), 0.57, 0.36),
|
||||
('M_Wheel', (0.60, 0.40, 0.25, 1), 0.90, 0.23),
|
||||
('M_Glass_Smoke', (0.013, 0.024, 0.082, 1), 0.38, 0.14),
|
||||
]:
|
||||
material = materials[name]
|
||||
bsdf = material.node_tree.nodes.get('Principled BSDF')
|
||||
bsdf.inputs['Base Color'].default_value = color
|
||||
material.diffuse_color = color
|
||||
bsdf.inputs['Metallic'].default_value = metallic
|
||||
bsdf.inputs['Roughness'].default_value = roughness
|
||||
if 'Body' in name:
|
||||
bsdf.inputs['Coat Weight'].default_value = 0.58
|
||||
bsdf.inputs['Coat Roughness'].default_value = 0.16
|
||||
bsdf.inputs['Emission Color'].default_value = (0.035, 0.002, 0.015, 1)
|
||||
bsdf.inputs['Emission Strength'].default_value = 0.16
|
||||
for obj in scene.objects:
|
||||
if obj.type == 'LIGHT' and obj.name.startswith('LOOKDEV'):
|
||||
if 'Key' in obj.name: obj.data.color = (0.42, 0.70, 1.0)
|
||||
if 'Rim' in obj.name: obj.data.color = (1.0, 0.12, 0.48)
|
||||
if 'Top' in obj.name: obj.data.color = (1.0, 0.73, 0.65)
|
||||
scene.world = scene.world.copy() if scene.world else None
|
||||
if scene.world: scene.world.color = (0.045, 0.018, 0.07)
|
||||
output = root_path / 'assets/blender/chromatic/nightdrive-chromatic.blend'
|
||||
bpy.data.libraries.write(str(output), {scene}, fake_user=True, compress=True)
|
||||
print('AUTHORED', scene.name, len(scene.objects), 'objects', output)
|
||||
51
assets/blender/chromatic/export-chromatic.py
Normal file
51
assets/blender/chromatic/export-chromatic.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""Export isolated authored source into material batches; leave lookdev editable."""
|
||||
import bpy, json, hashlib
|
||||
from mathutils import Matrix, Vector
|
||||
from pathlib import Path
|
||||
root_path=Path(__file__).resolve().parents[3]
|
||||
scene=bpy.data.scenes['Chromatic Nightdrive']
|
||||
bpy.context.window.scene=scene
|
||||
export_scene=bpy.data.scenes.new('Chromatic Export')
|
||||
root=bpy.data.objects.new('evolution-chase-car',None); export_scene.collection.objects.link(root)
|
||||
names={'M_Body_Gunmetal':'car-body','M_Body_Haunch':'body-haunches','M_Glass_Smoke':'rear-glass','M_Rear_Light':'rear-light-bar','M_Cyan_Accent':'car-underglow-source','M_Lower_Graphite':'body-trim','M_Wheel':'wheel-machining','M_Tire':'tires'}
|
||||
depsgraph=bpy.context.evaluated_depsgraph_get(); groups={}
|
||||
for obj in scene.objects:
|
||||
if obj.type not in ['MESH','CURVE'] or obj.name.startswith('LOOKDEV'): continue
|
||||
evaluated=obj.evaluated_get(depsgraph)
|
||||
mesh=bpy.data.meshes.new_from_object(evaluated,depsgraph=depsgraph); mesh.transform(obj.matrix_world)
|
||||
clone=bpy.data.objects.new('export-'+obj.name,mesh); export_scene.collection.objects.link(clone)
|
||||
key=obj.data.materials[0].name.split('.')[0]
|
||||
wheel=None
|
||||
for axle in ['front','rear']:
|
||||
for side in ['left','right']:
|
||||
if any(token in obj.name for token in [f'{axle}-wheel-{side}', f'{axle}-rim-{side}', f'{axle}-rim-ring-{side}', f'wheel-{axle}-{side}']):
|
||||
wheel=f'wheel-{axle}-{side}'
|
||||
groups.setdefault((key,wheel),[]).append(clone)
|
||||
bpy.context.window.scene=export_scene
|
||||
wheel_roots={}
|
||||
for (key,wheel),objects in groups.items():
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for obj in objects: obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active=objects[0]
|
||||
if len(objects)>1: bpy.ops.object.join()
|
||||
joined=bpy.context.object; joined.name='evolution-'+names[key]
|
||||
if wheel:
|
||||
if wheel not in wheel_roots:
|
||||
axle='front' if 'front' in wheel else 'rear'; side=-1 if 'left' in wheel else 1
|
||||
wheel_root=bpy.data.objects.new(wheel,None); export_scene.collection.objects.link(wheel_root)
|
||||
wheel_root.parent=root; wheel_root.location=(side*1.01,-1.62 if axle=='front' else 1.62,.42 if axle=='front' else .46)
|
||||
wheel_roots[wheel]=wheel_root
|
||||
wheel_root=wheel_roots[wheel]
|
||||
joined.data.transform(Matrix.Translation(-wheel_root.location))
|
||||
joined.parent=wheel_root
|
||||
else: joined.parent=root
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
output=root_path/'src/assets/nightdrive-grand-tourer-chromatic.glb'
|
||||
bpy.ops.export_scene.gltf(filepath=str(output),export_format='GLB',use_selection=True,use_active_scene=True,export_apply=True,export_animations=False,export_cameras=False,export_lights=False)
|
||||
triangles=0
|
||||
for obj in export_scene.objects:
|
||||
if obj.type=='MESH': obj.data.calc_loop_triangles(); triangles+=len(obj.data.loop_triangles)
|
||||
provenance={'asset':'Nightdrive chromatic grand tourer','source':'nightdrive-chromatic.blend','base':'../expressway/nightdrive-expressway.blend at 43e5103; original evolution at c9ac36e','authorship':'Original procedural modelling in Blender for this portfolio; no external assets or generated project evidence.','editable_scene':'Chromatic Nightdrive','material_groups':len(groups),'independent_wheels':4,'triangles':triangles,'export':'../../../src/assets/nightdrive-grand-tourer-chromatic.glb','sha256':hashlib.sha256(output.read_bytes()).hexdigest()}
|
||||
(root_path/'assets/blender/chromatic/nightdrive-chromatic.asset.json').write_text(json.dumps(provenance,indent=2)+'\n')
|
||||
bpy.context.window.scene=scene
|
||||
print(json.dumps(provenance))
|
||||
12
assets/blender/chromatic/nightdrive-chromatic.asset.json
Normal file
12
assets/blender/chromatic/nightdrive-chromatic.asset.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"asset": "Nightdrive chromatic grand tourer",
|
||||
"source": "nightdrive-chromatic.blend",
|
||||
"base": "../expressway/nightdrive-expressway.blend at 43e5103; original evolution at c9ac36e",
|
||||
"authorship": "Original procedural modelling in Blender for this portfolio; no external assets or generated project evidence.",
|
||||
"editable_scene": "Chromatic Nightdrive",
|
||||
"material_groups": 19,
|
||||
"independent_wheels": 4,
|
||||
"triangles": 31288,
|
||||
"export": "../../../src/assets/nightdrive-grand-tourer-chromatic.glb",
|
||||
"sha256": "89000428d04868cf71a8591fdf9b5096bcd8e732742a6760e6aa58b6d0a9e317"
|
||||
}
|
||||
BIN
assets/blender/chromatic/nightdrive-chromatic.blend
Normal file
BIN
assets/blender/chromatic/nightdrive-chromatic.blend
Normal file
Binary file not shown.
Reference in New Issue
Block a user