Created
March 1, 2026 08:33
-
-
Save akella/1f79dec225e5d03d8f9e6beb9782dd77 to your computer and use it in GitHub Desktop.
microsoft.ai
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const GOLDEN_ANGLE = float(2.39996323); | |
| const BOKEH_ITERATIONS = 50; | |
| const PI2 = float(Math.PI * 2); | |
| const uResolution = vec2(uniform(this.width), uniform(this.height)); | |
| let blueNoiseTexture = new THREE.TextureLoader().load(bluenoise); | |
| blueNoiseTexture.colorSpace = THREE.LinearSRGBColorSpace; | |
| blueNoiseTexture.minFilter = THREE.NearestFilter; | |
| blueNoiseTexture.magFilter = THREE.NearestFilter; | |
| blueNoiseTexture.wrapS = THREE.RepeatWrapping; | |
| blueNoiseTexture.wrapT = THREE.RepeatWrapping; | |
| const uBlueNoiseResolution = vec2(uniform(256), uniform(256)); | |
| const bokeh = Fn(([tex, inputUV, blurRadius, resolution]) => { | |
| const accumulatedColor = vec3(0.0).toVar(); | |
| const accumulatedWeights = vec3(0.0).toVar(); | |
| const accumulatedAlpha = float(0.0).toVar(); | |
| const aspectRatio = resolution.x.div(resolution.y); | |
| const pixelSize = vec2(float(1.0).div(aspectRatio), 1.0).mul(0.04).mul(0.075).mul(blurRadius); | |
| const r = float(1.0).toVar(); | |
| // Blue noise for per-pixel rotation to break banding | |
| const bnUV = fract( | |
| inputUV.mul(resolution).div(uBlueNoiseResolution).mul( | |
| vec2(uBlueNoiseResolution.x.div(uBlueNoiseResolution.y), 1.0) | |
| ) | |
| ); | |
| const blueNoise = texture(blueNoiseTexture, bnUV); | |
| const blueNoiseOffset = fract(blueNoise.r.sub(0.5).mul(PI2).div(PI2)).mul(PI2); | |
| const noiseOffset = blueNoiseOffset.sub(0.5).mul(0.01); | |
| const noiseAngle = noiseOffset.mul(PI2); | |
| const cosA = cos(noiseAngle); | |
| const sinA = sin(noiseAngle); | |
| Loop({ start: 0, end: int(BOKEH_ITERATIONS), name: 'i' }, ({ i }) => { | |
| const j = float(i).mul(GOLDEN_ANGLE); | |
| // Spiral sample position | |
| r.addAssign(float(1.0).div(r)); | |
| const spiralOffset = r.sub(1.0).mul(vec2(cos(j), sin(j))).mul(pixelSize); | |
| // Jitter to reduce pattern visibility | |
| const jitterAmount = float(0.05).mul(sin(j.mul(0.1)).mul(0.5).add(0.5)); | |
| const jitteredOffset = spiralOffset.mul( | |
| float(1.0).add(jitterAmount.mul(sin(j.mul(0.7).add(noiseOffset)))) | |
| ); | |
| // Rotate sample by blue noise angle | |
| const sampleOffset = vec2( | |
| cosA.mul(jitteredOffset.x).sub(sinA.mul(jitteredOffset.y)), | |
| sinA.mul(jitteredOffset.x).add(cosA.mul(jitteredOffset.y)) | |
| ); | |
| const colorSample = texture(tex, inputUV.add(sampleOffset)); | |
| // Weight: bright pixels get much higher weight → bright bokeh edges | |
| const srgbColor = pow(colorSample.rgb, vec3(1.0 / 2.2)); | |
| const bokehWeight = vec3(5.0).add(pow(srgbColor, vec3(9.0)).mul(150.0)); | |
| accumulatedAlpha.addAssign(colorSample.a); | |
| accumulatedColor.addAssign(colorSample.rgb.mul(bokehWeight)); | |
| accumulatedWeights.addAssign(bokehWeight); | |
| }); | |
| return vec4(accumulatedColor.div(accumulatedWeights), accumulatedAlpha.div(float(BOKEH_ITERATIONS))); | |
| }); | |
| let blurredPass = dof(nonblurredPass, this.focus, this.aperture, this.maxblur, this.circleOfConfusion); | |
| // let blurredPass = bokeh(nonblurredPass.getTextureNode(), uv(), this.maxblur, uResolution); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // step2 Worley | |
| const random2 = Fn(([p]) => { | |
| const d = vec2( | |
| dot(p, vec2(127.1, 311.7)), | |
| dot(p, vec2(269.5, 183.3)) | |
| ); | |
| return fract(sin(d).mul(43758.5453)); | |
| }); | |
| const worleyNoise = Fn(([p]) => { | |
| const intCell = floor(p).toVar(); | |
| const f = fract(p).toVar(); | |
| const minDist = float(10.0).toVar(); | |
| const mpoint = vec2(0).toVar(); | |
| Loop({ start: -1, end: 1, name: 'xIndex', condition: '<=' }, ({ xIndex }) => { | |
| Loop({ start: -1, end: 1, name: 'yIndex', condition: '<=' }, ({ yIndex }) => { | |
| const neighbor = vec2(xIndex, yIndex); | |
| let point = random2(intCell.add(neighbor)); | |
| point = float(0.5).add(sin(point.mul(6.24).add(time))); | |
| const diff = neighbor.add(point).sub(f); | |
| const dist = length(diff); | |
| If(dist.lessThan(minDist), () => { | |
| mpoint.assign(point); | |
| }); | |
| minDist.assign(min(minDist, dist)); | |
| }); | |
| }); | |
| return mpoint; | |
| }); | |
| let customUV = rotate(uv().sub(vec2(0.5)).mul(35), 0.56).mul(vec2(1, 0.2)); | |
| let mpoint = worleyNoise(customUV, time); | |
| let offset = mpoint.sub(vec2(0.5)).mul(0.2); | |
| let finalUV = uv().add(offset); | |
| let notBlurred = texture(scenePass.getTextureNode(), finalUV); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment