"""Native 4K PBR maps from an authored annual-ring surface; no bitmap upscaling. Blender writes portable RGB PNGs. Colour is explicitly encoded as sRGB; the normal and roughness images contain linear data. All maps share the same UVs. """ from pathlib import Path import bpy,numpy as np,json P=Path(__file__).resolve().parents[2];out=P/'assets/materials/phase11';out.mkdir(exist_ok=True) N=4096 axis=np.linspace(-1,1,N,dtype=np.float32);x=axis[None,:];y=axis[:,None] r=np.sqrt(x*x+y*y);a=np.arctan2(y,x) phase=r*12+.13*np.sin(a*3+r*9)+.07*np.sin(a*7-r*8) edge=np.abs(np.sin(phase*np.pi));line=np.clip((.27-edge)/.15,0,1);line=line*line*(3-2*line) fibres=np.sin(a*113+r*38)*np.sin(r*290+a*5) split=np.zeros((N,N),dtype=np.float32) for k in range(3): ca=.36+k*2.12;d=np.abs(np.arctan2(np.sin(a-ca-.012*np.sin(r*24)),np.cos(a-ca-.012*np.sin(r*24)))) split=np.maximum(split,np.clip((.014-d)/.011,0,1)*np.clip((r-(.48+.1*k))/(.91-.48-.1*k),0,1)) height=.54-.17*line-.35*split+.018*fibres rgba=np.ones((N,N,4),dtype=np.float32) def save(name,data,srgb=False): if data.ndim==2:data=data[:,:,None] if srgb:data=np.where(data<=.0031308,12.92*data,1.055*np.maximum(data,0)**(1/2.4)-.055) rgba[:,:,:3]=np.clip(data,0,1) im=bpy.data.images.new(name,width=N,height=N,alpha=False,float_buffer=False) im.colorspace_settings.name='Non-Color';im.pixels.foreach_set(rgba.ravel());im.filepath_raw=str(out/(name+'.png'));im.file_format='PNG';im.save();bpy.data.images.remove(im) colour=(1.2-.64*line)*(1+.07*fibres)*(1-.8*split) save('ringborke-cut-albedo-4k',colour[:,:,None]*np.array([.265,.147,.066],dtype=np.float32),True) gy,gx=np.gradient(height);normal=np.dstack((-gx*42,-gy*42,np.ones_like(height)));normal/=np.linalg.norm(normal,axis=2)[:,:,None] save('ringborke-cut-normal-4k',normal*.5+.5) save('ringborke-cut-roughness-4k',.78+.14*line+.06*split) (P/'assets-source/phase11/material-provenance.json').write_text(json.dumps({'method':'Original analytic Blender/Python surface bake','size':[N,N],'upscaled':False,'albedo_encoding':'sRGB','normal_encoding':'linear, tangent space +Y','roughness_encoding':'linear','generator':'assets-source/phase11/bake_cutwood.py','inputs':'Annual ring field, warped fibres and radial growth checks; no external images'},indent=2)+'\n') print('CUTWOOD_BAKE_PASS: three native 4096px material maps',flush=True)