O que Teardown Cinema faz?
Mesmo motor do teardown (código three.js, um relógio, captura quadro a quadro, trilha sonora feita em código), propósito oposto. Teardown explica, então tem painéis. Cinema mostra, então não tem nada na tela exceto o mundo. Exemplo funcional, todos os arquivos: example/orison nesta skill (o filme de 30 segundos Orison e sua página interativa).
Precisa da skill teardown ao lado desta para node_modules (three, esbuild, playwright), sims/capture.mjs e sfx/. A captura não precisa do Chromium próprio do Playwright: defina CHROMIUM para o Chrome instalado. Se o download travar, o Chrome funciona.
O método, em ordem
- Uma imagem mestre. Gere uma imagem complexa com qualquer modelo de imagem forte. Com o aplicativo Codex:
codex exec --skip-git-repo-check -s workspace-write -C <dir> - < prompt.txt. O prompt sai da sua máquina, então mantenha conteúdo confidencial fora dele. Peça algo com estrutura que você possa nomear: uma cúpula, costelas, anéis, fitas. O Codex não informa qual modelo de imagem usou. - Placas de textura a partir da mestre. Anexe com
-i master.pnge gere placas planas, frontais e uniformemente iluminadas: painel de vidro, rendilhado de metal sobre preto puro, seda, um planeta sobre preto, uma seção transversal de anel, uma criatura vista de cima. Preto é o que você corta. Essas placas são o motivo pelo qual o resultado mantém o detalhe da pintura. Gere uma de cada vez. - Meça a mestre, depois reconstrua. Leia as proporções da imagem em pixels e transforme-as em unidades de mundo antes de escrever a geometria. Quase todo erro inicial aqui foi uma proporção que ninguém mediu.
- Uma entrada controla o corpo. Escolha a batida da criatura ou máquina, escreva em JS e GLSL, e poseie cada parte a partir dela no shader de vértices. Nada é animado por keyframes. Veja
shared/kin.js,shared/glsl.js. - Tomadas, não um sobrevoo. Uma lista de tomadas, cada uma uma função pura do tempo dentro dela, com cortes secos e uma correção de cor por tomada. Cortes são o que fazem disso um filme. Veja
orison-film/shots.js. - Compare com a mestre a cada passada. Renderize o quadro principal ao lado da imagem e anote o que difere. Corrija. Repita.
- Trilha sonora em código na mesma linha do tempo com o
sfx/do teardown. Vejascore.py. - A página é o mesmo mundo com uma mão diferente na câmera. O scroll escolhe um ponto em um caminho, um clique é uma batida, um arrasto olha ao redor. Veja
orison-live/.
Layout
meu-filme/
brief/ imagem mestre e prompts
assets/ placas, como .jpg (embutidas na página)
shared/ o mundo: kin.js, glsl.js, sky.js, creature.js, world.js
meu-filme-film/ main.js, shots.js, timeline.json
meu-filme-live/ main.js, path.js, audio.js, body.html, style.css
score.py
Comandos
Execute a partir da pasta do filme. SKILL_DIR é esta skill, T é a skill irmã teardown. No Windows PowerShell 5.1 use npx.cmd e npm.cmd e não &&.
node "$SKILL_DIR/build.mjs" ./meu-filme-film ./meu-filme-live
export CHROMIUM="C:/Program Files/Google/Chrome/Application/chrome.exe" # a captura pode usar o Chrome instalado
# um quadro, ou uma folha, em uma qualidade escolhida: --config aponta para {"samples": N}
node "$T/sims/capture.mjs" meu-filme-film --size 1920x1080 --dpr 1 --config s.json --still 12.5 --out frame.png
node "$T/sims/capture.mjs" meu-filme-film --size 1920x1080 --dpr 1 --config s.json --stills 3,8,12,18,23,29 --cols 3 --out sheet.png
# o filme inteiro
node "$T/sims/capture.mjs" meu-filme-film --size 1920x1080 --dpr 1 --fps 24 --crf 15 --config s.json --out silent.mp4
python "$T/run_sfx.py" score.py
ffmpeg -i silent.mp4 -i teardown-out/minha-trilha.wav -map 0:v -map 1:a -c:v copy -c:a aac -b:a 256k -shortest -movflags +faststart film.mp4
--stills organiza em grade através de uma paleta, então as folhas mostram falsa bandagem. Julgue cor e bandagem nos quadros completos ao lado delas.
O que kit/cinema.js oferece
new Cinema({canvas, samples, fps, shutter, msaa}), depois cine.frame(t, draw, look).
Um quadro de filme é a média de N sub-quadros. Cada sub-quadro move o tempo dentro do obturador (motion blur verdadeiro), a câmera no disco da lente com o plano focal mantido (profundidade de campo verdadeira, também através de camadas transparentes), e um deslocamento de subpixel (anti-aliasing). Marcha de raios ditherizada converge com ele. A pós-processamento é executada uma vez na imagem HDR média: bloom, estria anamórfica, feixes de luz em direção a um ponto, ACES, correção de cor, grão, vinheta. samples: 1 é o mesmo pipeline para páginas ao vivo.
Números de um laptop com uma Radeon 780M integrada, a 1920x1080: 32 amostras por quadro levaram 2,3 segundos por quadro, incluindo a codificação: 27 minutos para 30 segundos de filme a 24 fps. Um rascunho a 960x480 e 4 amostras levou 41 segundos para o filme inteiro, então use rascunhos livremente. A página ao vivo executou de 37 a 51 fps em todo o scroll a 1600x900, e mais alto em leituras pontuais sem mais nada rodando. Verifique gpu: na saída da captura; um renderizador por software significa que as flags da GPU não pegaram.
Regras que decidiram se funcionou
- Nenhum texto no quadro. Sem rótulos, números, cartelas de título ou legendas. A imagem carrega tudo.
- Empacote exatamente um three.js.
build.mjsforça isso. Uma segunda cópia perto do filme (o próprionode_modulesde um projeto) falha silenciosamente: o ambiente de reflexão perde seus níveis de desfoque e o metal fica escuro. - Coloque a renderização ao lado da mestre no mesmo tamanho e liste o que difere. Proporções primeiro, depois cor. Meça posições em pixels e converta-as em direções. A maior parte da semelhança em Orison veio dessas passadas.
- Mantenha a profundidade de campo rasa apenas para coisas pequenas. Desfoque pesado em um gigante faz com que pareça uma miniatura. Os raios da lente do filme são de 0,012 a 0,03 unidades em uma criatura de 26 unidades.
- Amostras de tempo e lente não devem compartilhar uma sequência. Se compartilharem, o desfoque traça arcos visíveis. Ângulo áureo para a lente, Halton base 5 para o tempo.
- Nunca use
pow()em um valor que pode ser negativo. D3D retorna NaN, e um pixel NaN se espalha pelo bloom como retângulos pretos. Escrevax*x.max(1.-ndv,0.), não1.-ndv. O kit também sanitiza suas entradas. smoothstep(a, b, x)invertido coma > bretorna 0 no Windows. Escreva1.-smoothstep(b,a,x).- Placas espelhadas em uma superfície estreitante: mapeie com Mercator para que as células permaneçam redondas, e espelhe apenas as células grandes da placa. As finas viram confete de perto.
- Painéis alinhados com a luz devem ser mais claros, não mais brilhantes. Caso contrário, o interior de um corpo de vidro nunca é lido.
- Uma abertura escura precisa de algo vivo dentro. Um brilho fraco através da névoa carrega até a primeira batida.
- Nuvens ao vivo: meia resolução com uma média móvel; marcha mais densa perto da câmera. Nuvens são suaves, então nada se perde.
- O primeiro segundo de uma página ao vivo é compilação de shaders. Compile antes do primeiro quadro e mostre uma pequena pulsação enquanto isso, sem texto de carregamento.
Regras da página ao vivo
Todas as regras ao vivo do teardown se aplicam (níveis de qualidade, aquecer os shaders). Também: abra na imagem mestre e dissolva para o 3D assim que os shaders estiverem prontos; os níveis sobem novamente quando os quadros se recuperam, não apenas descem; sem rótulos na página; um nome acessível no canvas e em qualquer botão; um alvo de clique de pelo menos 44 px; o som só começa após o primeiro gesto; o corpo se estabiliza após uma batida em vez de subir para sempre; a qualidade diminui de acordo com a taxa de quadros medida, sem perguntar.
Revisão
Você não pode assistir vídeo, mas pode ler quadros. Folha de cada tomada primeiro, quadros completos para o que a folha sinalizar, depois --stills every:0.2 --from A --to B através de uma transição. Leia uma folha de um quadro por segundo da codificação final: isso mostra o que o codificador escreveu. Meça a trilha com ffmpeg -af ebur128=peak=true. Uma pessoa ainda precisa assistir ao filme e ouvir a trilha uma vez; diga isso ao relatar.
Para um host que adiciona seu próprio esqueleto de documento, como um Artefato Claude, construa com FRAGMENT=1 e defina o nome com PAGE_TITLE: ele também escreve <nome>.fragment.html.