kernel omino_stamp_32 < namespace : "omino"; vendor : "omino"; version : 1; description : "stamp a pattern with an image"; > { input image4 src; // the underlying image input image4 tile; // an image to stamp with output pixel4 dst; parameter float2 sourceSize < minValue:float2(1,1); maxValue:float2(2048,2048); defaultValue:float2(512,512); aeUIControl: "aePoint"; aePointRelativeDefaultValue: float2(1,1); >; parameter float2 tileSize < minValue:float2(1,1); maxValue:float2(2048,2048); defaultValue:float2(256,256); >; parameter float2 tileAnchor < minValue:float2(0,0); maxValue:float2(2048,2048); defaultValue:float2(128,128); >; parameter float2 tilingCenter < minValue:float2(0,0); maxValue:float2(2048,2048); defaultValue:float2(128,128); >; parameter float2 tilingSpacing < minValue:float2(1,1); maxValue:float2(2048,2048); defaultValue:float2(128,128); >; parameter float tileScale < minValue:0.0; maxValue:10.0; defaultValue:0.3; >; parameter float bricking < minValue:-1.0; maxValue:1.0; defaultValue:0.0; >; parameter float rot < minValue:-60.0; maxValue:60.0; defaultValue:0.0; aeUIControl:"aeAngle"; >; parameter float tileRot < minValue:-60.0; maxValue:60.0; defaultValue:0.0; aeUIControl:"aeAngle"; >; parameter int overlaps < minValue:0; maxValue:5; defaultValue:1; >; parameter float affectsTileSizeAmount < minValue:0.0; maxValue:100.0; defaultValue:0.0; aeUIControl:"aePercentSlider"; >; parameter float affectsTileColorAmount < minValue:0.0; maxValue:100.0; defaultValue:0.0; aeUIControl:"aePercentSlider"; >; parameter float affectsTileRotationAmount < minValue:0.0; maxValue:100.0; defaultValue:0.0; aeUIControl:"aePercentSlider"; >; void evaluatePixel() { float2 sampleCo = outCoord(); float2 co = sampleCo; pixel4 dstPixel = float4(0,0,0,0); float rotRad = radians(rot); float rotSin = sin(rotRad); float rotCos = cos(rotRad); float2x2 rotFwd = float2x2(rotCos,-rotSin,rotSin,rotCos); float2x2 rotBwd = float2x2(rotCos,rotSin,-rotSin,rotCos); // which rep-cell are we within, to start? // the centerest cell is tilingCenter - tilingSpacing/2 co -= tilingCenter; co *= rotFwd; // discover the y-row of the nearest-cell float2 cellCo; cellCo.y = floor(co.y / tilingSpacing.y); // incorporate the y-row for bricking, to discover the x-column of nearest-cell cellCo.x = floor((co.x - cellCo.y * bricking * tilingSpacing.x) / tilingSpacing.x); // assign co to the center of the nearest cell co = (cellCo + float2(cellCo.y * bricking,0.0)) * tilingSpacing; co = co * rotBwd + tilingCenter; // co is now the center of the nearest cell we're tiling. float2 underCo = co; // finally, assign co to the relative positiong within that cell. co = sampleCo - co; float range = float(overlaps); float i,j; for(i = -range; i <= range; i++) { for(j = -range; j <= range; j++) { float2 pluckOffset = float2((i + j * bricking) * tilingSpacing.x,j * tilingSpacing.y); pixel4 underPixel = sampleLinear(src,clamp(underCo - pluckOffset * rotBwd,float2(1,1),sourceSize - float2(2,2))); float2 pluckCo = co + pluckOffset * rotBwd; float scaleDown = tileScale * (100.0 - affectsTileSizeAmount * underPixel.g) * 0.01; if(scaleDown < 0.00001) scaleDown = 0.00001; // work in rotation of the stamp image float tileRotRad = radians(tileRot + 3.60 * underPixel.r * affectsTileRotationAmount); float2x2 tileRotFwd = float2x2(cos(tileRotRad),-sin(tileRotRad),sin(tileRotRad),cos(tileRotRad)); pluckCo = (pluckCo / scaleDown) * tileRotFwd + tileAnchor; pixel4 pluckPixel = sampleLinear(tile,pluckCo); pluckPixel.rgb = (affectsTileColorAmount * pluckPixel.rgb * underPixel.rgb + (100.0 - affectsTileColorAmount) * pluckPixel.rgb) * 0.01; dstPixel.rgb = pluckPixel.a * pluckPixel.rgb + dstPixel.rgb * (1.0 - pluckPixel.a); dstPixel.a = dstPixel.a + pluckPixel.a - dstPixel.a * pluckPixel.a; } } dst = dstPixel; // dst = underPixel; } }