Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Engine/Core/Configuration/PNDefaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ public struct PNDefaults {
/// Amplifies the brightness of pixels that pass the luminance threshold for bloom.
public var luminanceAmplifier: Float16 = 1.2
/// The sigma value for the Gaussian blur applied to blooming areas.
public var blurSigma: Float = 10.0
public var blurSigma: Float = 1.0
/// Rendering scale - scale of the image in relation to frame resolution
public var renderingScale: Float = 0.33
}
/// Configuration for Screen Space Ambient Occlusion (SSAO) visual effect.
/// SSAO simulates subtle self-shadowing in creases, holes, and surfaces to enhance realism in rendered images. These parameters control the visual quality and performance of the effect.
Expand Down
6 changes: 3 additions & 3 deletions Engine/Core/Rendering/Jobs/Bloom/PNBloomSplitJob.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ struct PNBloomSplitJob: PNComputeJob {
self.pipelineState = pipelineState
self.inputTexture = inputTexture
self.outputTexture = outputTexture
guard let inputTexture = inputTexture.texture else {
guard let outputTexture = outputTexture.texture else {
return nil
}
dispatchSize = MTLSize(width: inputTexture.width,
height: inputTexture.height)
dispatchSize = MTLSize(width: outputTexture.width,
height: outputTexture.height)
}
func compute(encoder: MTLComputeCommandEncoder, supply: PNFrameSupply) {
encoder.setComputePipelineState(pipelineState)
Expand Down
1 change: 1 addition & 0 deletions Engine/Core/Rendering/Stages/PNPipeline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class PNPipeline: PNStage {
let postprocessStage = PNPostprocessStage(input: combineStage.io.output.color[0],
velocities: gBufferStage.io.output.color[3],
bloomBlurSigma: PNDefaults.shared.shaders.postprocess.bloom.blurSigma,
bloomRenderingScale: PNDefaults.shared.shaders.postprocess.bloom.renderingScale,
device: device,
renderingSize: renderingSize) else {
return nil
Expand Down
16 changes: 9 additions & 7 deletions Engine/Core/Rendering/Stages/PNPostprocessStage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,22 @@ struct PNPostprocessStage: PNStage {
init?(input: PNTextureProvider,
velocities: PNTextureProvider,
bloomBlurSigma: Float,
bloomRenderingScale: Float,
device: MTLDevice,
renderingSize: CGSize) {
guard let bloomSplitTexture = device.makeTextureBloomSplitC(size: renderingSize) else {
return nil
}
guard let postprocessOutputTexture = device.makeTexturePostprocessOutput(size: renderingSize) else {
let bloomSplitTextureSize = CGSize(width: renderingSize.width * CGFloat(bloomRenderingScale),
height: renderingSize.height * CGFloat(bloomRenderingScale))

guard let bloomSplitTexture = device.makeTextureBloomSplitC(size: bloomSplitTextureSize),
let postprocessOutputTexture = device.makeTexturePostprocessOutput(size: renderingSize) else {
return nil
}
self.bloomSplitTexture = bloomSplitTexture
self.postprocessOutputTexture = postprocessOutputTexture
guard let bloomSplitJob = PNBloomSplitJob.make(device: device,
inputTexture: input,
outputTexture: PNStaticTexture(bloomSplitTexture)),
let splitBlurredTexture = device.makeTexture(descriptor: .bloomSplitC(size: renderingSize)),
let splitBlurredTexture = device.makeTexture(descriptor: .bloomSplitC(size: bloomSplitTextureSize)),
let postprocessMergeJob = PNPostprocessMergeJob.make(device: device,
sceneTexture: input,
velocities: velocities,
Expand All @@ -47,15 +49,15 @@ struct PNPostprocessStage: PNStage {
}
func draw(commandBuffer: MTLCommandBuffer, supply: PNFrameSupply) {
guard let bloomSplitEncoder = commandBuffer.makeComputeCommandEncoder() else {
return
fatalError("Failed to create an encoder for bloom split")
}
bloomSplitJob.compute(encoder: bloomSplitEncoder, supply: supply)
bloomSplitEncoder.endEncoding()
gaussianBlurJob.encode(commandBuffer: commandBuffer,
sourceTexture: bloomSplitTexture,
destinationTexture: splitBlurredTexture)
guard let postprocessMergeEncoder = commandBuffer.makeComputeCommandEncoder() else {
return
fatalError("Failed to create an encoder for postprocess merge")
}
postprocessMergeJob.compute(encoder: postprocessMergeEncoder, supply: supply)
postprocessMergeEncoder.endEncoding()
Expand Down
14 changes: 8 additions & 6 deletions Engine/Shaders/Bloom/BloomSplit.metal
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ using namespace metal;
kernel void kernelBloomSplit(texture2d<half, access::read> inputTexture [[texture(kAttributeBloomSplitComputeShaderTextureInput)]],
texture2d<half, access::write> outputTexture [[texture(kAttributeBloomSplitComputeShaderTextureOutput)]],
uint2 inposition [[thread_position_in_grid]]) {
half3 color = inputTexture.read(inposition.xy).xyz;
if (luminance(color) > luminanceThreshold) {
outputTexture.write(half4(color * amplification, 1.0h), inposition.xy);
} else {
outputTexture.write(half4(0.0h, 0.0h, 0.0h, 1.0h), inposition.xy);
}
float2 texcoord = float2(inposition.x / static_cast<float>(outputTexture.get_width()),
inposition.y / static_cast<float>(outputTexture.get_height()));
float2 resolution = float2(inputTexture.get_width(), inputTexture.get_height());
uint2 inTexel = uint2(texcoord * resolution);
half3 color = inputTexture.read(inTexel).rgb;
half mask = luminance(color) > luminanceThreshold;
half3 amplifiedColor = color * amplification;
outputTexture.write(half4(mask * amplifiedColor, 1.0h), inposition.xy);
}
2 changes: 1 addition & 1 deletion Engine/Shaders/Postprocess/Grain.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
#include <simd/simd.h>

simd::half3 grain(float time,
simd::half2 texcoord,
simd::float2 texcoord,
simd::half3 inputColor);
4 changes: 2 additions & 2 deletions Engine/Shaders/Postprocess/Grain.metal
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ using namespace metal;
#define MEAN 0.0h
#define VARIANCE 0.5h

half3 grain(float time, half2 texcoord, half3 inputColor) {
half3 grain(float time, float2 texcoord, half3 inputColor) {
float t = time * float(SPEED);
float seed = dot(float2(texcoord), float2(12.9898, 78.233));
float seed = dot(texcoord, float2(12.9898, 78.233));
float noise = fract(sin(seed) * 43758.5453 + t);
noise = gaussian(noise, float(MEAN), float(VARIANCE) * float(VARIANCE));
half3 grain = half3(noise) * (1.0h - inputColor.xyz);
Expand Down
15 changes: 9 additions & 6 deletions Engine/Shaders/Postprocess/PostprocessMerge.metal
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@

using namespace metal;

kernel void postprocessMerge(texture2d<half> inputTexture [[texture(kAttributePostprocessMergeComputeShaderTextureOriginal)]],
texture2d<half> brightAreasTexture [[texture(kAttributePostprocessMergeComputeShaderTextureBrightAreas)]],
texture2d<half> velocityTexture [[texture(kAttributePostprocessMergeComputeShaderTextureVelocities)]],
kernel void postprocessMerge(texture2d<half, access::sample> inputTexture [[texture(kAttributePostprocessMergeComputeShaderTextureOriginal)]],
texture2d<half, access::read> brightAreasTexture [[texture(kAttributePostprocessMergeComputeShaderTextureBrightAreas)]],
texture2d<half, access::sample> velocityTexture [[texture(kAttributePostprocessMergeComputeShaderTextureVelocities)]],
texture2d<half, access::write> outputTexture [[texture(kAttributePostprocessMergeComputeShaderTextureOutput)]],
constant float & time [[buffer(kAttributePostprocessMergeComputeShaderBufferTime)]],
uint2 inposition [[thread_position_in_grid]],
uint2 threads [[threads_per_grid]]) {

half2 texcoord{half(inposition.x)/half(threads.x),
half(inposition.y)/half(threads.y)};
float2 texcoord{float(inposition.x)/float(threads.x),
float(inposition.y)/float(threads.y)};

half3 blurredImage = motionBlur(inputTexture,
velocityTexture,
inposition,
1.0h,
5).rgb;

half3 bloomColor = brightAreasTexture.read(inposition.xy).xyz;
float2 bloomResolution = float2(brightAreasTexture.get_width(),
brightAreasTexture.get_height());
uint2 bloomTexel = uint2(bloomResolution * texcoord);
half3 bloomColor = brightAreasTexture.read(bloomTexel).xyz;
half4 inputColor = half4(bloomColor + blurredImage, 1);
half4 vignetteColor = vignette(inputColor, half4(0, 0, 0, 1), texcoord, 0.8h, 2.0h);
half4 grainColor = half4(grain(time, texcoord, vignetteColor.xyz), 1.0h);
Expand Down
2 changes: 1 addition & 1 deletion Engine/Shaders/Postprocess/Vignette.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

metal::half4 vignette(metal::half4 fragmentColor,
metal::half4 vignetteColor,
metal::half2 position,
metal::float2 position,
half fromRadius,
half toRadius);
4 changes: 2 additions & 2 deletions Engine/Shaders/Postprocess/Vignette.metal
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ using namespace metal;

half4 vignette(half4 fragmentColor,
half4 vignetteColor,
half2 position,
float2 position,
half fromRadius,
half toRadius) {
half radius = length(half2(0.5h, 0.5h) - position) * 2.0h;
half radius = length(float2(0.5f, 0.5f) - position) * 2.0h;
half ratio = saturate(radius - fromRadius) / (toRadius - fromRadius);
return mix(fragmentColor, vignetteColor, ratio);
}
Loading