Add clay pieces, masking, and topology editing to sculpt
Add pastel presets, piece selection and colors, mask brushes, subdivision and conservative decimation with bounded worker operations and mixed undo history. Amp-Thread-ID: https://ampcode.com/threads/T-01a0b4b4-202c-73f1-984d-9a55c88f9c83 Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
@@ -12,12 +12,12 @@ function wire(v) {
|
||||
const shader = `
|
||||
struct Camera { right:vec4f, up:vec4f, forward:vec4f, center:vec4f, color:vec4f }
|
||||
@group(0) @binding(0) var<uniform> camera:Camera;
|
||||
struct Out { @builtin(position) position:vec4f, @location(0) normal:vec3f }
|
||||
@vertex fn vertex(@location(0) p:vec3f, @location(1) n:vec3f)->Out {
|
||||
struct Out { @builtin(position) position:vec4f, @location(0) normal:vec3f, @location(1) mask:f32, @location(2) material:vec3f }
|
||||
@vertex fn vertex(@location(0) p:vec3f, @location(1) mask:f32, @location(2) n:vec3f, @location(3) material:vec4f)->Out {
|
||||
let d=p-camera.center.xyz;
|
||||
var o:Out;
|
||||
o.position=vec4f(dot(d,camera.right.xyz)/camera.right.w,dot(d,camera.up.xyz)/camera.up.w,0.5-dot(d,camera.forward.xyz)/32.0,1.0);
|
||||
o.normal=vec3f(dot(n,camera.right.xyz),dot(n,camera.up.xyz),dot(n,camera.forward.xyz));return o;
|
||||
o.normal=vec3f(dot(n,camera.right.xyz),dot(n,camera.up.xyz),dot(n,camera.forward.xyz));o.mask=mask;o.material=material.xyz;return o;
|
||||
}
|
||||
@fragment fn fragment(o:Out)->@location(0) vec4f {
|
||||
let n=normalize(o.normal);
|
||||
@@ -25,7 +25,8 @@ struct Out { @builtin(position) position:vec4f, @location(0) normal:vec3f }
|
||||
let fill=max(dot(n,normalize(vec3f(0.8,0.0,0.4))),0.0);
|
||||
let rim=pow(1.0-max(n.z,0.0),3.0);
|
||||
let spec=pow(max(dot(n,normalize(vec3f(-0.3,0.45,1.0))),0.0),48.0);
|
||||
let color=camera.color.xyz*(0.24+key*0.65+fill*0.16)+vec3f(0.12,0.14,0.16)*rim+vec3f(0.12)*spec;
|
||||
let base=mix(o.material,o.material*0.22,clamp(o.mask,0.0,1.0));
|
||||
let color=base*(0.24+key*0.65+fill*0.16)+vec3f(0.12,0.14,0.16)*rim+vec3f(0.12)*spec;
|
||||
return vec4f(pow(color,vec3f(1.0/2.2)),1.0);
|
||||
}`;
|
||||
|
||||
@@ -64,13 +65,13 @@ export class Renderer {
|
||||
await r.core.createRowsBatch([
|
||||
{
|
||||
name: "sculptVertices",
|
||||
rows: mesh.positions.length / 3,
|
||||
rows: Math.max(1, mesh.positions.length / 3),
|
||||
stride: 32,
|
||||
format: "f32",
|
||||
},
|
||||
{
|
||||
name: "sculptIndices",
|
||||
rows: Math.ceil(mesh.indices.length / 4),
|
||||
rows: Math.max(1, Math.ceil(mesh.indices.length / 4)),
|
||||
stride: 16,
|
||||
format: "u32",
|
||||
},
|
||||
@@ -124,7 +125,9 @@ export class Renderer {
|
||||
arrayStride: 32,
|
||||
attributes: [
|
||||
{ format: "float32x3", offset: 0, shaderLocation: 0 },
|
||||
{ format: "float32x3", offset: 16, shaderLocation: 1 },
|
||||
{ format: "float32", offset: 12, shaderLocation: 1 },
|
||||
{ format: "float32x3", offset: 16, shaderLocation: 2 },
|
||||
{ format: "unorm8x4", offset: 28, shaderLocation: 3 },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -175,16 +178,33 @@ export class Renderer {
|
||||
writeVertices(first, count) {
|
||||
const p = this.mesh.positions,
|
||||
n = this.mesh.normals,
|
||||
v = this.vertices.view;
|
||||
v = this.vertices.view,
|
||||
bytes = new Uint8Array(v.buffer, v.byteOffset, v.byteLength),
|
||||
pieces = this.mesh.pieces ?? [];
|
||||
let pieceIndex = pieces.findIndex(
|
||||
(piece) => first < piece.vertexStart + piece.vertexCount,
|
||||
);
|
||||
for (let i = first; i < first + count; i++) {
|
||||
const a = i * 3,
|
||||
b = i * 8;
|
||||
v[b] = p[a];
|
||||
v[b + 1] = p[a + 1];
|
||||
v[b + 2] = p[a + 2];
|
||||
v[b + 3] = this.mesh.masks?.[i] ?? 0;
|
||||
v[b + 4] = n[a];
|
||||
v[b + 5] = n[a + 1];
|
||||
v[b + 6] = n[a + 2];
|
||||
while (
|
||||
pieceIndex >= 0 &&
|
||||
pieceIndex < pieces.length - 1 &&
|
||||
i >= pieces[pieceIndex].vertexStart + pieces[pieceIndex].vertexCount
|
||||
)
|
||||
pieceIndex++;
|
||||
const piece = pieces[pieceIndex];
|
||||
const color = piece?.color ?? [0.5, 0.3, 0.2];
|
||||
for (let k = 0; k < 3; k++)
|
||||
bytes[b * 4 + 28 + k] = Math.round(color[k] * 255);
|
||||
bytes[b * 4 + 31] = 255;
|
||||
}
|
||||
}
|
||||
writeCamera(camera) {
|
||||
|
||||
Reference in New Issue
Block a user