Skip to content

Commit

Permalink
Merge pull request #384 from RagnarokResearchLab/fix-water-transparency
Browse files Browse the repository at this point in the history
Fix alpha compositing for translucent water surfaces
  • Loading branch information
rdw-software authored Feb 28, 2024
2 parents 3ffe75f + 31652c0 commit 8660f7a
Show file tree
Hide file tree
Showing 10 changed files with 24 additions and 36 deletions.
7 changes: 3 additions & 4 deletions Core/NativeClient/Renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,7 @@ local Renderer = {

function Renderer:InitializeWithGLFW(nativeWindowHandle)
Renderer:CreateGraphicsContext(nativeWindowHandle)

-- Need to compute the preferred texture format first
self.backingSurface:UpdateConfiguration()
Renderer:CompileMaterials(self.backingSurface.preferredTextureFormat)
Renderer:CompileMaterials(self.backingSurface.textureFormat)

Renderer:CreateUniformBuffers()

Expand Down Expand Up @@ -134,6 +131,8 @@ function Renderer:CreateGraphicsContext(nativeWindowHandle)

printf("Creating depth buffer with texture dimensions %d x %d", viewportWidth, viewportHeight)
self.depthStencilTexture = DepthStencilTexture(device, viewportWidth, viewportHeight)

self.backingSurface:UpdateConfiguration()
end

function Renderer:CompileMaterials(outputTextureFormat)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ function GroundMeshDrawingPipeline:Construct(wgpuDeviceHandle, textureFormatID)
dstFactor = ffi.C.WGPUBlendFactor_OneMinusSrcAlpha,
operation = ffi.C.WGPUBlendOperation_Add,
},
alpha = {
srcFactor = ffi.C.WGPUBlendFactor_One,
dstFactor = ffi.C.WGPUBlendFactor_OneMinusSrcAlpha,
operation = ffi.C.WGPUBlendOperation_Add,
},
}),
writeMask = ffi.C.WGPUColorWriteMask_All,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ function WaterPlaneDrawingPipeline:Construct(wgpuDeviceHandle, textureFormatID)
dstFactor = ffi.C.WGPUBlendFactor_OneMinusSrcAlpha,
operation = ffi.C.WGPUBlendOperation_Add,
},
alpha = {
srcFactor = ffi.C.WGPUBlendFactor_One,
dstFactor = ffi.C.WGPUBlendFactor_OneMinusSrcAlpha,
operation = ffi.C.WGPUBlendOperation_Add,
},
}),
writeMask = ffi.C.WGPUColorWriteMask_All,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ local Device = require("Core.NativeClient.WebGPU.Device")
local format = string.format

local ScreenshotCaptureTexture = {
OUTPUT_TEXTURE_FORMAT = ffi.C.WGPUTextureFormat_RGBA8UnormSrgb,
OUTPUT_TEXTURE_FORMAT = ffi.C.WGPUTextureFormat_RGBA8Unorm,
}

function ScreenshotCaptureTexture:Construct(wgpuDevice, width, height)
Expand Down
6 changes: 1 addition & 5 deletions Core/NativeClient/WebGPU/Shaders/BasicTriangleShader.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,5 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let materialColor = vec4f(uMaterialInstanceData.diffuseRed, uMaterialInstanceData.diffuseGreen, uMaterialInstanceData.diffuseBlue, uMaterialInstanceData.materialOpacity);
let finalColor = in.color * diffuseTextureColor.rgb * materialColor.rgb;

// Gamma-correction:
// WebGPU assumes that the colors output by the fragment shader are given in linear space
// When setting the surface format to BGRA8UnormSrgb it performs a linear to sRGB conversion
let gammaCorrectedColor = pow(finalColor.rgb, vec3f(2.2));
return vec4f(gammaCorrectedColor, diffuseTextureColor.a * materialColor.a + DEBUG_ALPHA_OFFSET);
return vec4f(finalColor, diffuseTextureColor.a * materialColor.a + DEBUG_ALPHA_OFFSET);
}
7 changes: 1 addition & 6 deletions Core/NativeClient/WebGPU/Shaders/TerrainGeometryShader.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,5 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {

// Should be a no-op if fog is disabled, since the fogFactor would be zero
let foggedColor = mix(fragmentColor.rgb, uPerSceneData.fogColor.rgb, in.fogFactor);

// Gamma-correction:
// WebGPU assumes that the colors output by the fragment shader are given in linear space
// When setting the surface format to BGRA8UnormSrgb it performs a linear to sRGB conversion
let gammaCorrectedColor = pow(foggedColor.rgb, vec3f(2.2));
return vec4f(gammaCorrectedColor, diffuseTextureColor.a + DEBUG_ALPHA_OFFSET);
return vec4f(foggedColor.rgb, diffuseTextureColor.a + DEBUG_ALPHA_OFFSET);
}
6 changes: 1 addition & 5 deletions Core/NativeClient/WebGPU/Shaders/UserInterfaceShader.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,5 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
// Currently the same buffer is used when RML assigns the same texture, which won't work
let finalColor = in.color * diffuseTextureColor * vec4f(1.0, 1.0, 1.0, 1.0);

// Gamma-correction:
// WebGPU assumes that the colors output by the fragment shader are given in linear space
// When setting the surface format to BGRA8UnormSrgb it performs a linear to sRGB conversion
let gammaCorrectedColor = vec4f(pow(finalColor.rgb, vec3f(2.2)), finalColor.w);
return vec4f(gammaCorrectedColor);
return vec4f(finalColor);
}
6 changes: 1 addition & 5 deletions Core/NativeClient/WebGPU/Shaders/WaterSurfaceShader.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,5 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let materialColor = vec4f(uMaterialInstanceData.diffuseRed, uMaterialInstanceData.diffuseGreen, uMaterialInstanceData.diffuseBlue, uMaterialInstanceData.materialOpacity);
let finalColor = in.color * diffuseTextureColor.rgb * materialColor.rgb;

// Gamma-correction:
// WebGPU assumes that the colors output by the fragment shader are given in linear space
// When setting the surface format to BGRA8UnormSrgb it performs a linear to sRGB conversion
let gammaCorrectedColor = pow(finalColor.rgb, vec3f(2.2));
return vec4f(gammaCorrectedColor, diffuseTextureColor.a * materialColor.a + DEBUG_ALPHA_OFFSET);
return vec4f(finalColor.rgb, diffuseTextureColor.a * materialColor.a + DEBUG_ALPHA_OFFSET );
}
14 changes: 5 additions & 9 deletions Core/NativeClient/WebGPU/Surface.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ local Surface = {
BACKING_SURFACE_OUTDATED = "The backing surface is outdated and can't be used (window resized or moved?)",
BACKING_SURFACE_TIMEOUT = "The backing surface couldn't be accessed in time (CPU or GPU too busy?)",
},
textureFormat = ffi.C.WGPUTextureFormat_BGRA8Unorm,
}

function Surface:Construct(wgpuInstance, wgpuAdapter, wgpuDevice, glfwWindow)
Expand All @@ -33,23 +34,16 @@ function Surface:Construct(wgpuInstance, wgpuAdapter, wgpuDevice, glfwWindow)
end

function Surface:UpdateConfiguration()
local preferredTextureFormat = webgpu.bindings.wgpu_surface_get_preferred_format(self.wgpuSurface, self.wgpuAdapter)
self.preferredTextureFormat = preferredTextureFormat -- Required to create the render pipeline
assert(
preferredTextureFormat == ffi.C.WGPUTextureFormat_BGRA8UnormSrgb,
"Only sRGB texture formats are currently supported"
)

local textureViewDescriptor = self.wgpuTextureViewDescriptor
textureViewDescriptor.dimension = ffi.C.WGPUTextureViewDimension_2D
textureViewDescriptor.format = preferredTextureFormat
textureViewDescriptor.format = self.textureFormat
textureViewDescriptor.mipLevelCount = 1
textureViewDescriptor.arrayLayerCount = 1
textureViewDescriptor.aspect = ffi.C.WGPUTextureAspect_All

local surfaceConfiguration = self.wgpuSurfaceConfiguration
surfaceConfiguration.device = self.wgpuDevice
surfaceConfiguration.format = preferredTextureFormat
surfaceConfiguration.format = self.textureFormat
surfaceConfiguration.usage = ffi.C.WGPUTextureUsage_RenderAttachment

-- The underlying framebuffer may be different if DPI scaling is applied, but let's ignore that for now
Expand All @@ -62,12 +56,14 @@ function Surface:UpdateConfiguration()

webgpu.bindings.wgpu_surface_configure(self.wgpuSurface, surfaceConfiguration)

local preferredTextureFormat = webgpu.bindings.wgpu_surface_get_preferred_format(self.wgpuSurface, self.wgpuAdapter)
printf(
"Surface configuration changed: Frame buffer size is now %dx%d (preferred texture format: %d)",
viewportWidth,
viewportHeight,
tonumber(preferredTextureFormat)
)
self.preferredTextureFormat = preferredTextureFormat
end

function Surface:AcquireTextureView()
Expand Down
2 changes: 1 addition & 1 deletion Core/NativeClient/WebGPU/Texture.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ local new = ffi.new
local math_floor = math.floor

local Texture = {
DEFAULT_TEXTURE_FORMAT = ffi.C.WGPUTextureFormat_RGBA8Unorm, -- TBD: WGPUTextureFormat_BGRA8UnormSrgb ?
DEFAULT_TEXTURE_FORMAT = ffi.C.WGPUTextureFormat_RGBA8Unorm,
MAX_TEXTURE_DIMENSION = 4096,
ERROR_DIMENSIONS_NOT_POWER_OF_TWO = "Texture dimensions should always be a power of two",
ERROR_DIMENSIONS_EXCEEDING_LIMIT = "Texture dimensions must not exceed the configured GPU limit",
Expand Down

0 comments on commit 8660f7a

Please sign in to comment.