算法来自于Advanced Renderman,又加了一下边边角角。不是很完整,在源文件里能看到有很多参数没实现。 //voronoi_h.sl void voronoi_f1( point P; float jitter; output float f1; output point pos1; ) { point cell = point(floor(P[0]),floor(P[1]),floor(P[2]))+vector(0.5); uniform float i,j,k; point currentCell,currentPos; f1 = 1e9; for(i = -1;i<=1;i+=1) for(j = -1;j<=1;j+=1) for(k = -1;k<=1;k+=1){ currentCell = cell+vector(i,j,k); currentPos = currentCell + jitter*(vector cellnoise(currentCell)-.5); float l = length(currentPos - P); if (l<f1){ f1 = l; pos1 = currentPos; }; } } void voronoi_f1f2( point P; float jitter; output float f1; output point pos1; output float f2; output point pos2; ) { point cell = point(floor(P[0]),floor(P[1]),floor(P[2]))+vector(0.5); uniform float i,j,k; point currentCell,currentPos; f1 = 1e9; f2 = f1; for(i = -1;i<=1;i+=1) for(j = -1;j<=1;j+=1) for(k = -1;k<=1;k+=1){ currentCell = cell+vector(i,j,k); currentPos = currentCell + jitter*(vector cellnoise(currentCell)-.5); float l = length(currentPos - P); if (l<f1){ f2 = f1; pos2 = pos1; f1 = l; pos1 = currentPos; } else if(l<f2){ f2 = l; pos2 = currentPos; } } } #include "voronoi_h.sl" color locIllumVoronoi( normal N; color Ka; color C; color Ks; float roughness; ){ extern vector I; vector IN = normalize(I); return (diffuse(N)*C + Ka + Ks*specular(N,-IN,roughness)); } surface voronoi( color Ka = .1; //matrix M = 1; float scale = 1; float jitter = 1; float jitterWall = 0.1; color Ks_Cell = .7; color Ks_Wall = .3; float roughness_Cell = 0.5; float roughness_Wall = 0.2; color color_Wall = 1; float wallThreshold = 0.1; float wallBlurness = 0.3; float height_Wall = 0.1; float height_Cell = 0.05; ) { vector Nf = faceforward(normalize(N),I); point Pw = transform("world",P); /* matrix tmpM = 2; Pw = transform(1/tmpM,Pw); uniform float aaa = 0; if (aaa<1){ printf("%m/n",placement); aaa = 1; } Ci = color(Pw); */ / float f1,f2; point pos1,pos2; voronoi_f1f2(Pw/scale,jitter,f1,pos1,f2,pos2); float value; value = smoothstep(wallThreshold-wallBlurness*.1,wallThreshold+wallBlurness*.1,f2 - f1); value = clamp(value,0,1); // 0 - wall // 1 - cell color CWall,CCell,C,illumWall,illumCell,illum; float hWall,hCell,h; // Displacement if (value!=0) hCell = (1-f1) * height_Cell; if (value!=1) hWall = height_Wall; h = mix(hWall,hCell,value); vector Nw = normalize(ntransform("world",N)); Pw += Nw*h; P = transform("world","current",Pw); N = calculatenormal(P); Nf = faceforward(normalize(N),I); /* if (value == 0) Ci = color(1,0,0); else if (value == 1) Ci = color(0,1,0); else Ci = value; Ci = diffuse(Nf); */ // Shading if (value!=0){ float _v = random(); CCell = color "hsv" (cellnoise(pos1),1,1); illumCell = locIllumVoronoi(Nf,Ka,CCell,Ks_Cell,roughness_Cell); } if (value!=1){ CWall = color_Wall; illumWall = locIllumVoronoi(Nf,Ka,CWall,Ks_Wall,roughness_Wall); } C = mix(CWall,CCell,value); illum = mix(illumWall,illumCell,value); // Shading Ci =C*illum*Cs; }