///|
/// Post-processing effects: bloom, vignette, color grading, denoising stubs.
pub fn apply_vignette(pixels : Array[Vec3], width : Int, height : Int, strength~ : Double) -> Array[Vec3] {
let result = Array::new(capacity=pixels.length())
let cx = width.to_double() / 2.0
let cy = height.to_double() / 2.0
let max_dist = (cx * cx + cy * cy).sqrt()
for j in 0.. Array[Vec3] {
let bloom = Array::new(capacity=pixels.length())
for j in 0.. threshold {
bloom.push(pixels[idx].mul_scalar(intensity * (lum - threshold) / lum.max(0.001)))
} else {
bloom.push({ x: 0.0, y: 0.0, z: 0.0 })
}
}
}
let kernel_size = 5
let bloom_blurred = Array::new(capacity=bloom.length())
for j in 0..= 0 && nx < width && ny >= 0 && ny < height {
let den = dx.to_double() * dx.to_double() + dy.to_double() * dy.to_double()
let weight = gaussian_filter(den.sqrt(), 3.0)
accum = accum + bloom[ny * width + nx].mul_scalar(weight)
count = count + weight
}
}
}
if count > 0.0 {
accum = accum.div_scalar(count)
}
bloom_blurred.push(accum)
}
}
let result = Array::new(capacity=pixels.length())
for j in 0.. Array[Vec3] {
let result = Array::new(capacity=pixels.length())
let lum_weights = { x: 0.2126, y: 0.7152, z: 0.0722 }
for j in 0.. Array[Vec3] {
let result = Array::new(capacity=pixels.length())
let mut rng = default_rng()
for j in 0.. Array[Vec3] {
let result = Array::new(capacity=pixels.length())
for j in 0..= 0 && nx < width && ny >= 0 && ny < height {
let neighbor = pixels[ny * width + nx]
let diff = (center - neighbor).length()
let color_weight = @math.exp(-diff * 10.0)
accum = accum + neighbor.mul_scalar(color_weight)
total_weight = total_weight + color_weight
}
}
}
if total_weight > 0.0 {
result.push(accum.div_scalar(total_weight))
} else {
result.push(center)
}
}
}
result
}