| """Run a small physical rendering demo with bundled weights; CPU, no account.""" |
| from pathlib import Path |
| import argparse,json,sys |
| ROOT=Path(__file__).resolve().parents[1] |
| sys.path.insert(0,str(ROOT)) |
| import numpy as np |
| from aureole import WorldMemory,freeze,draw,correct |
| from aureole.core import proposal_from_bound |
| from aureole.renderer import Scene,VisibilityPrior,receiver_grid,light_grid,unoccluded,physical_table |
|
|
|
|
| def run(output,frames=24,side=48): |
| if frames<1 or side<2:raise ValueError("Need frames>=1, side>=2") |
| output=Path(output);output.mkdir(parents=True,exist_ok=True) |
| points=receiver_grid(side,side);lights=light_grid();scene=Scene.create(300) |
| prior=VisibilityPrior(ROOT/"models/visibility_prior.npz") |
| p=prior(scene.features(points[:,None,:],lights[None,:,:])) |
| memory=WorldMemory(len(points),len(lights),"demo-scene-300") |
| rng=np.random.default_rng(3101);ids=np.arange(len(points));b=unoccluded(points,lights) |
| images={};events=[] |
| for frame in range(frames): |
| if frame==frames//2: |
| scene=scene.changed() |
| v=memory.predict(ids,p) |
| s=freeze(b*v[...,None],proposal_from_bound(b,v,memory.trusted(ids),active=True)) |
| j=draw(s,2,rng);vis=scene.visibility(points[:,None,:],lights[j]) |
| values=b[np.arange(len(ids))[:,None],j]*vis[...,None] |
| result=correct(s,j,values) |
| conflicts=memory.commit(ids,j,vis,revise_on_conflict=True) |
| events.append({"frame":frame,"conflicting_ray_entries":conflicts,"epoch_after":memory.epoch}) |
| if frame in {0,max(0,frames//2-1),frames//2,frames-1}: |
| images[f"frame_{frame:03d}"]=result.reshape(side,side,3) |
| |
| images["reference_final"]=physical_table(scene,points,lights,b).sum(1).reshape(side,side,3) |
| np.savez_compressed(output/"linear_frames.npz",**images) |
| memory.save(output/"world_memory.npz") |
| import matplotlib |
| matplotlib.use("Agg") |
| import matplotlib.pyplot as plt |
| fig,axes=plt.subplots(1,len(images),figsize=(3*len(images),3.6)) |
| for ax,(label,im) in zip(np.atleast_1d(axes),images.items()): |
| ax.imshow(np.clip(im,0,1)**(1/2.2),origin="lower") |
| ax.set_title(label.replace("_"," "),fontsize=10);ax.axis("off") |
| fig.suptitle("AUREOLE-R CPU demo: two fresh shadow rays per receiver / frame",fontsize=13) |
| fig.text(.5,.035,"Preview clips negative estimates and applies gamma. Statistical outputs remain linear in the NPZ.",ha="center",fontsize=9) |
| fig.tight_layout(rect=(0,.08,1,.92));fig.savefig(output/"demo.png",dpi=160);plt.close(fig) |
| report={"frames":frames,"receiver_count":len(points),"emitters":len(lights),"rays":frames*len(points)*2, |
| "events":events,"final_mse":float(np.mean((images[f"frame_{frames-1:03d}"]-images["reference_final"])**2)), |
| "scope":"small CPU direct-light demo; no SR/FG/game/GPU implementation"} |
| (output/"demo.json").write_text(json.dumps(report,indent=2)+"\n") |
| print(json.dumps(report,indent=2)) |
|
|
| if __name__=="__main__": |
| parser=argparse.ArgumentParser();parser.add_argument("--output",default="demo_output") |
| parser.add_argument("--frames",type=int,default=24);parser.add_argument("--side",type=int,default=48) |
| args=parser.parse_args();run(args.output,args.frames,args.side) |
|
|