Graphics: Switch glyph atlases to R8 instead of A8

A8 can't be supported efficiently on API lacking texture swizzle support (DX, WebGL, WebGPU), so we swizzle in the shader instead
This commit is contained in:
SirLynix 2023-02-22 19:11:41 +01:00
parent b38f9dc79b
commit 5833ce573d
10 changed files with 46 additions and 13 deletions

View File

@ -26,6 +26,8 @@ namespace Nz
GLenum swizzleG;
GLenum swizzleB;
GLenum swizzleA;
inline bool HasSwizzle() const;
};
inline std::optional<GLTextureFormat> DescribeTextureFormat(PixelFormat pixelFormat);

View File

@ -10,14 +10,19 @@
namespace Nz
{
inline bool GLTextureFormat::HasSwizzle() const
{
return swizzleR != GL_RED || swizzleG != GL_GREEN || swizzleB != GL_BLUE || swizzleA != GL_ALPHA;
}
inline std::optional<GLTextureFormat> DescribeTextureFormat(PixelFormat pixelFormat)
{
// TODO: Fill this switch
switch (pixelFormat)
{
case PixelFormat::A8: return GLTextureFormat{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_ONE, GL_ONE, GL_ONE, GL_RED };
case PixelFormat::BGR8: return GLTextureFormat{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ONE };
case PixelFormat::BGR8_SRGB: return GLTextureFormat{ GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ONE };
case PixelFormat::BGR8: return GLTextureFormat{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
case PixelFormat::BGR8_SRGB: return GLTextureFormat{ GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
case PixelFormat::BGRA8: return GLTextureFormat{ GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
case PixelFormat::BGRA8_SRGB: return GLTextureFormat{ GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
case PixelFormat::Depth16: return GLTextureFormat{ GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_RED, GL_ZERO, GL_ZERO, GL_ZERO };
@ -27,8 +32,10 @@ namespace Nz
case PixelFormat::Depth32FStencil8: return GLTextureFormat{ GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_RED, GL_GREEN, GL_ZERO, GL_ZERO };
case PixelFormat::L8: return GLTextureFormat{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_RED, GL_RED, GL_RED, GL_ONE };
case PixelFormat::LA8: return GLTextureFormat{ GL_RG8, GL_RG, GL_UNSIGNED_BYTE, GL_RED, GL_RED, GL_RED, GL_GREEN };
case PixelFormat::RGB8: return GLTextureFormat{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ONE };
case PixelFormat::RGB8_SRGB: return GLTextureFormat{ GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ONE };
case PixelFormat::R8: return GLTextureFormat{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
case PixelFormat::RG8: return GLTextureFormat{ GL_RG8, GL_RG, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
case PixelFormat::RGB8: return GLTextureFormat{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
case PixelFormat::RGB8_SRGB: return GLTextureFormat{ GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
case PixelFormat::RGBA8: return GLTextureFormat{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
case PixelFormat::RGBA8_SRGB: return GLTextureFormat{ GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
case PixelFormat::RGBA16F: return GLTextureFormat{ GL_RGBA16F, GL_RGBA, GL_FLOAT, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };

View File

@ -21,6 +21,10 @@ namespace Nz
case VK_FORMAT_D24_UNORM_S8_UINT: return PixelFormat::Depth24Stencil8;
case VK_FORMAT_D32_SFLOAT: return PixelFormat::Depth32F;
case VK_FORMAT_D32_SFLOAT_S8_UINT: return PixelFormat::Depth32FStencil8;
case VK_FORMAT_R8_UNORM: return PixelFormat::R8;
case VK_FORMAT_R8G8_UNORM: return PixelFormat::RG8;
case VK_FORMAT_R8G8B8_UNORM: return PixelFormat::RGB8;
case VK_FORMAT_R8G8B8_SRGB: return PixelFormat::RGB8_SRGB;
case VK_FORMAT_R8G8B8A8_UNORM: return PixelFormat::RGBA8;
case VK_FORMAT_R8G8B8A8_SRGB: return PixelFormat::RGBA8_SRGB;
default: break;
@ -274,6 +278,8 @@ namespace Nz
case PixelFormat::Depth24Stencil8: return VK_FORMAT_D24_UNORM_S8_UINT;
case PixelFormat::Depth32F: return VK_FORMAT_D32_SFLOAT;
case PixelFormat::Depth32FStencil8: return VK_FORMAT_D32_SFLOAT_S8_UINT;
case PixelFormat::R8: return VK_FORMAT_R8_UNORM;
case PixelFormat::RG8: return VK_FORMAT_R8G8_UNORM;
case PixelFormat::RGB8: return VK_FORMAT_R8G8B8_UNORM;
case PixelFormat::RGB8_SRGB: return VK_FORMAT_R8G8B8_SRGB;
case PixelFormat::RGBA8: return VK_FORMAT_R8G8B8A8_UNORM;

View File

@ -39,7 +39,7 @@ namespace Nz
TextureInfo textureInfo;
textureInfo.width = size.x;
textureInfo.height = size.y;
textureInfo.pixelFormat = PixelFormat::A8;
textureInfo.pixelFormat = PixelFormat::R8;
textureInfo.type = ImageType::E2D;
textureInfo.usageFlags = TextureUsage::ShaderSampling | TextureUsage::TransferSource | TextureUsage::TransferDestination;

View File

@ -80,7 +80,7 @@ fn main(input: FragIn) -> FragOut
let color = settings.BaseColor;
const if (HasUV)
color *= TextureOverlay.Sample(input.uv).rrrg;
color.a *= TextureOverlay.Sample(input.uv).r;
const if (HasColor)
color *= input.color;

View File

@ -129,7 +129,7 @@ fn main(input: VertToFrag) -> FragOut
let color = settings.BaseColor;
const if (HasUV)
color *= TextureOverlay.Sample(input.uv).rrrg;
color.a *= TextureOverlay.Sample(input.uv).r;
const if (HasColor)
color *= input.color;

View File

@ -115,7 +115,7 @@ fn main(input: VertToFrag) -> FragOut
let color = settings.BaseColor;
const if (HasUV)
color *= TextureOverlay.Sample(input.uv).rrrg;
color.a *= TextureOverlay.Sample(input.uv).r;
const if (HasColor)
color *= input.color;

View File

@ -233,6 +233,8 @@ namespace Nz
case PixelFormat::Undefined:
return false;
// the following formats are emulated using texture swizzling which isn't supported on WebGL
// https://registry.khronos.org/webgl/specs/latest/2.0/#5.19
case PixelFormat::A8:
case PixelFormat::BGR8:
case PixelFormat::BGR8_SRGB:
@ -240,6 +242,12 @@ namespace Nz
case PixelFormat::BGRA8_SRGB:
case PixelFormat::L8:
case PixelFormat::LA8:
#ifdef NAZARA_PLATFORM_WEB
return false;
#else
[[fallthrough]];
#endif
case PixelFormat::R8:
case PixelFormat::R8I:
case PixelFormat::R8UI:

View File

@ -54,12 +54,20 @@ namespace Nz
if (!context.DidLastCallSucceed())
throw std::runtime_error("failed to create texture");
#ifndef NAZARA_PLATFORM_WEB
m_texture.SetParameteri(GL_TEXTURE_MAX_LEVEL, m_textureInfo.levelCount);
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_R, format->swizzleR);
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_G, format->swizzleG);
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_B, format->swizzleB);
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_A, format->swizzleA);
#ifndef NAZARA_PLATFORM_WEB
if (format->swizzleR != GL_RED)
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_R, format->swizzleR);
if (format->swizzleG != GL_GREEN)
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_G, format->swizzleG);
if (format->swizzleB != GL_BLUE)
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_B, format->swizzleB);
if (format->swizzleA != GL_ALPHA)
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_A, format->swizzleA);
#endif
}

View File

@ -438,6 +438,8 @@ namespace Nz
case PixelFormat::Depth24Stencil8:
case PixelFormat::Depth32F:
case PixelFormat::Depth32FStencil8:
case PixelFormat::R8:
case PixelFormat::RG8:
case PixelFormat::RGB8:
case PixelFormat::RGB8_SRGB:
case PixelFormat::RGBA8: