Commit Graph

21 Commits

Author SHA1 Message Date
BFlat 558168d09a Merge pull request #55 from Agapenordev/fix/import-gpu-oom
Never crash importing meshes with many materials
2026-11-02 12:33:22 +07:00
bflatastic 8efd62aeaa Viewport: no ghost edges in the subsurface blur
Skin and other scattering materials showed copies of the silhouette
running parallel to it: the blur's taps sit pixels apart when the mean
free path is wide on screen, and a tap that left the mesh dropped out
of the sum, so the light stepped at every tap spacing from the edge.
Taps are now shifted per pixel and per accumulated frame, and a tap
across a depth discontinuity takes the centre's light instead of
dropping out.

Fixes #86.
2026-11-02 07:59:35 +07:00
Agapenordev fd9768a28d Merge remote-tracking branch 'origin/main' into fix/import-gpu-oom 2026-11-02 01:24:39 +01:00
bflatastic 963008635c display.set: refuse unknown environment names
The built-in environment list moves to core (render re-exports it), so
the engine can name the valid ones in the error.

Fixes #65.
2026-11-02 05:34:40 +07:00
Agapenordev b0cd961e90 Merge remote-tracking branch 'origin/main' into fix/import-gpu-oom 2026-11-01 22:23:11 +01:00
Agapenordev 3591e02758 Address review: WebGPU verdicts, repaints, lasting memory notice
- Allocation checks never take an unanswered error scope as success:
  native backends block on the verdict; the browser's WebGPU answers
  later, so the full-size texture waits beside the bound placeholder
  (tiles go into it under discarded scopes) and Renderer::prepare
  installs it on success, or keeps the placeholder and reports the set
  on failure. The UI keeps drawing frames while a verdict is pending.
- The GPU side wakes the UI when it records an uncaptured error or an
  allocation failure, so the notice shows even when the app is idle;
  failures are collected after prepare, where late verdicts land.
- Sets the GPU could not hold share one sticky notice (dismissible,
  listing them) instead of a six-second toast each, since they are not
  retried.
- The out-of-memory error is reported as the cause rather than the
  follow-on invalid-texture error.
- The notice no longer uses "▸", which the UI fonts lack (egui panics
  on a missing glyph).

Tests: a late texture stays unbound until accepted; a late rejection
keeps the placeholder and is reported once; a verdict that never comes
counts as a failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 22:12:12 +01:00
bflatastic bd128ab181 Wireframes show the mesh's polygons, not their triangles
Importers fan-triangulate quads and n-gons, and the 3D and UV wireframes drew
every triangle edge, so a quad mesh showed its triangulation. Meshes now carry a
per-triangle mask of the diagonals the importer added (Mesh::diagonals), and the
wireframe leaves them out (Mesh::wire_edges), unless a UV seam split one from its
twin.

- OBJ reads polygons whole (tobj without triangulation) and fans them itself.
- OBJ, PLY and the polygon sink (FBX, COLLADA, USD, Alembic) share one fan,
  RawMesh::polygon, which records the diagonals.
- The built-in meshes mark their grid quads.
- glTF and STL store triangles only, so they keep every edge.

Fixes #41
2026-11-02 03:20:57 +07:00
Agapenordev 098602ec49 Never crash importing meshes with many materials
Every texture set (one per mesh material) allocated full-size display
textures (base color, emissive, ORM, normal, height, aux, with mips) as
soon as it was created: ~130 MB of GPU memory per set at the default
2048 import size. A 16-material OBJ ran a 4 GB laptop GPU out of memory
and wgpu's default error handler panicked, closing the app.

- Display and aux textures start as 1×1 neutral placeholders and get
  their full size with the first non-neutral tile (or aux image), so an
  import costs no GPU memory until its sets are painted.
- That allocation runs in an error scope: on failure the texture keeps
  its placeholder (no retry per tile), the failure is logged and the UI
  shows a toast naming the texture set and the Viewport ▸ Texture
  resolution setting. Painting and export are unaffected.
- The app installs an uncaptured-error handler that logs and reports
  wgpu errors as toasts instead of panicking.
- The GPU path tracer takes each set's size from its largest texture,
  since any kind (base color included) may now be a placeholder.

Tests: 40 sets of 2048 allocate nothing until painted, one painted kind
allocates alone, the aux texture allocates on its first upload, painted
placeholders render, and the GPU tracer matches the CPU with a default
base color beside varying roughness (fails with the old size logic).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 21:05:50 +01:00
bflatastic 814765d96d Viewport backdrop in the interface's slate
The views' studio backdrop is a cool slate, lighter at the top, matching the panels around them (post pass, CPU and GPU path tracers), and the viewport token and its lettering follow it.
2026-11-01 19:46:15 +07:00
bflatastic e2637115df Displacement in the viewport's key-light shadows
The shadow pass draws the dense copy and displaces it like the 3D view, so a displaced surface
shadows itself instead of being shadowed as if it were still smooth.

- shaders/displace.wgsl: displace_by_height, shared by mesh.wgsl and shadow.wgsl
- the shadow pipeline takes the set bind group (height and sampler) and a displacement vec4
  (on, world units per unit of height with the height strength, vertex spacing)
- while it displaces, the cached shadow map is re-rendered when the set textures change
- test: with flat height, displaced shadows match the plain mesh's
2026-11-01 13:35:53 +07:00
bflatastic 8b8655a6f3 Displacement in the path tracers
Rendering mode traces displaced geometry when the display has displacement on, so path-traced
renders show the viewport's silhouettes and the displaced surface shadows itself.

- render::displace: the viewport's dense subdivision of the mesh, each vertex moved along its
  normal by its set's height (box-filtered to the mip the vertex shader samples) times the
  height strength, at the viewport's scale (world length per UV / 16)
- trace_geometry gives the GPU and CPU tracers the displaced mesh and BVH; Rendering mode,
  texturecraft-cli render --samples and MCP viewport_render use it
- Rendering mode keeps the traced geometry until the mesh, a set's content or a height
  strength changes (display tweaks don't rebuild it)
- subdivide::vertices shared by the renderer's mesh upload and displacement
- test: a uniform height lifts the dense plane by height x strength x world per UV / 16
2026-11-01 13:35:53 +07:00
bflatastic 2ddb156d69 Neutral names in code and packaging; README in the Crafting Apps layout
- Code comments, crate descriptions, the MCP stroke schema and the Linux package descriptions
  describe features in their own words instead of naming the reference application or other
  vendors' products (file format names stay)
- The README follows the layout the other Crafting Apps use (VectorCraft): a look around, made
  in TextureCraft, why TextureCraft, quick start with the agent setup, status, downloads per
  platform, the Crafting Apps, star history, license; no trademark footer
- The detailed feature list moves to docs/features.md
- A new path-traced render of the built-in crate textured with smart materials

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:55:42 +07:00
bflatastic 3bab36ec84 Accumulate effect frames with an exact per-pixel copy (no filtered read)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 16:15:23 +07:00
bflatastic f4496037ea Sample opens ready to paint; exact per-pixel reads in the DoF and subsurface passes
- The startup sample adds an empty paint layer on top of each stack and selects it (strokes on
  the bottom layer were hidden under the smart material)
- Depth of field and subsurface blur read same-size targets by pixel, not by filtered UV, so
  inert settings change nothing on any adapter (software adapters blended neighbours)
- CLI help lists .abc and builtin:udim_plane

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:38:44 +07:00
bflatastic cd65c8ebfd Headless render tests: compare inert-feature renders within one level (software adapters)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:43:00 +07:00
bflatastic 1e88b9041f Smooth 8K strokes, decal handles, displacement, refraction, release readiness
- Strokes pre-blend their commit while painting and recompose committed tiles at low
  priority: the 8K stroke-end frame drops from 30-42 ms to 12-19 ms
- Texture set resize runs in the background (8K: 3 s to 0.5 s, UV padding map from island
  borders only)
- Decal move/scale/rotate handles; FBX and USD high-poly textures for the color map;
  viewport displacement from the height channel; screen-space refraction of the scene
- CI pinned to Rust 1.96.0; FreeBSD VM sized for hosted runners; release builds embed
  craft-fonts; file associations for FBX, COLLADA, USD and Alembic on every platform
- README, release checklist, NOTICE and attribution brought up to date

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 13:25:10 +07:00
bflatastic 6bf3cb83d4 Format the workspace (cargo fmt)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:28:37 +07:00
bflatastic 55387bf0fd GPU baking, Alembic, templates, translations and 8K responsiveness
- Baking: per-map ray settings (AO, thickness, bent normals), GPU ray-traced baking with CPU
  fallback (~12x), color map from textured glTF high polys
- Files: Alembic (Ogawa) and FBX 6 import, per-tile UDIM resolution, converting a set to UV
  tiles, project templates, preserving painted strokes on mesh reimport
- UI: translations (French, German, Spanish, Portuguese, Italian, Japanese, Chinese, Korean)
  with a live language picker and CJK fonts, closed panels reopen where they were, viewport
  texture resolution setting, frame-budgeted scene sync for 8K sets
- Web: loading screen, WebGL2 notice, app-captured shortcuts, touch navigation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:23:28 +07:00
bflatastic 81d3f5c14c GPU path tracing, depth of field, cameras, glass, filters and decals
- Rendering mode traces on the GPU (compute shaders, ~25x the CPU tracer) with CPU fallback;
  CLI/MCP render --samples uses the GPU unless --cpu
- Depth of field in the viewport and the path tracer; multiple cameras with glTF import;
  transmission/IOR, coat normal and screen-space subsurface blur; exact 8-bit normal decode
- Filter library (18 filters incl. warp, color balance, gradient map, posterize, MatFinish)
  with a Filters shelf tab; geometry decals; clone from the current layer; anchors inside a
  content stack; instances across texture-set resolutions; drag saved smart materials

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 09:06:22 +07:00
bflatastic bdbb52c9b6 UDIM tiles, USD import/export, coat/sheen/anisotropy/subsurface shading
- UV tiles: auto-detected UDIM texture sets as one atlas per set, padding kept inside tiles,
  one file per tile with the $udim export token, builtin:udim_plane
- USD: usda/usdc/usdz import (Crate reader with LZ4) and export with UsdPreviewSurface
- Shader lobes: clear coat, sheen, anisotropy and subsurface scattering channels in the
  viewport and the path tracer; car paint, velvet, brushed steel, skin and wax materials;
  glTF clearcoat/sheen export
- Color swatch popups no longer stay open

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:45:14 +07:00
bflatastic ec859420d5 TextureCraft: clean-room 3D texture painting in pure Rust
An open-source, clean-room implementation of a Substance 3D Painter-style texturing
workflow, written in pure Rust with egui and wgpu.

- Layer stack with 32 blend modes, masks, generators, content effects and anchor points
- Painting, projection, smudge, clone, path, lasso fill, particle brush and quick mask
- 43 procedural materials, 17 smart materials and 10 smart masks
- Mesh map baking with high-poly, cage and match-by-name support
- PBR viewport with HDR environments, TAA and a path-traced Rendering mode
- glTF, FBX, COLLADA, OBJ, PLY and STL import; texture export presets; OBJ and GLB export
- Dockable Painter-style UI, shortcut editor, web build, MCP server and CLI

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:33:13 +07:00