Node inputs: float samples float filtersize float radial float uniformSampling Node output: output color out_color Node code: /* _______ generate a series of random coordinates ______ (implementation of Hammersley point set) */ float sampleCoordX[ samples ]; float sampleCoordY[ samples ]; uniform float iter = 0; // find the num of decimals uniform float numOfDecimals = ceil( log( samples, 2 ) ); uniform float revBinValues[ numOfDecimals ]; for( iter = 0; iter < samples; iter += 1 ) { // generate binary fractions and their reversed uniform float decimal = 0; uniform float remainder = iter; for( decimal = (numOfDecimals - 1); decimal >= 0; decimal -= 1 ) { uniform float power = pow( 2, decimal ); if ( remainder >= power ) { revBinValues[ decimal ] = 1; remainder -= power; } else revBinValues[ decimal ] = 0; } // convert back to floats uniform float x = 0; uniform float y = 0; uniform float index = 0; for( index = 1; index <= numOfDecimals; index += 1 ) { x += ( pow( 2, -index ) * revBinValues[ numOfDecimals-index ] ); y += ( pow( 2, -index ) * revBinValues[ index-1 ] ); } // scale x to compensate for the non-power-of-two sample numbers x *= pow( 2, numOfDecimals ) / samples ; // store coordinates sampleCoordX[ iter ] = x; sampleCoordY[ iter ] = y; } // ___________________________________ float randomNumber = float random(); void HammersleyToRadial( float shadowSampling; output float sampleCoordX; output float sampleCoordY ) { // if these samples are for light shadowing sampling if ( shadowSampling == 1 ){ // samples should be evenly distributed sampleCoordY = sqrt( sampleCoordY ); // vary the samples positions per shaded point extern float randomNumber; sampleCoordX += randomNumber; } float angleOfSample = sampleCoordX * 2 * PI; sampleCoordX = cos( angleOfSample ) * sampleCoordY; // cos = adj / hypot sampleCoordY = sqrt( pow( sampleCoordY, 2 ) - pow( sampleCoordX, 2 ) ); // a2 + b2 = c2 if( angleOfSample > PI ) sampleCoordY *= -1; } // ___________________________________ color c = color( 1,1,1 ); extern float u; extern float v; for( iter = 0; iter < samples; iter += 1 ) { if( radial == 1 ) { HammersleyToRadial( uniformSampling, sampleCoordX[ iter ], sampleCoordY[ iter ] ); sampleCoordX[ iter ] /= 2; sampleCoordY[ iter ] /= 2; sampleCoordX[ iter ] += 0.5; sampleCoordY[ iter ] += 0.5; } float samplePointU, samplePointV, samplePointColor; samplePointU = smoothstep( sampleCoordX[ iter ] - filtersize, sampleCoordX[ iter ], u ); samplePointU -= smoothstep( sampleCoordX[ iter ], sampleCoordX[ iter ] + filtersize, u ); samplePointV = smoothstep( sampleCoordY[ iter ] - filtersize, sampleCoordY[ iter ], v ); samplePointV -= smoothstep( sampleCoordY[ iter ], sampleCoordY[ iter ] + filtersize, v ); samplePointColor = samplePointU * samplePointV; if( samplePointColor > 0 ) c -= samplePointColor; } out_color = c;