renderer/opengl: explicit texture options

This sets up for a couple improvments (see TODO comments) and also sets
the glyph atlas textures to nearest neighbor sampling since we can do
that now that we never scale glyphs.
This commit is contained in:
Qwerasd
2025-07-05 20:58:15 -06:00
parent 02d82720d2
commit 87f35bd1c1
3 changed files with 50 additions and 4 deletions

View File

@ -92,6 +92,30 @@ pub const Format = enum(c_uint) {
_, _,
}; };
/// Minification filter for textures.
pub const MinFilter = enum(c_int) {
nearest = c.GL_NEAREST,
linear = c.GL_LINEAR,
nearest_mipmap_nearest = c.GL_NEAREST_MIPMAP_NEAREST,
linear_mipmap_nearest = c.GL_LINEAR_MIPMAP_NEAREST,
nearest_mipmap_linear = c.GL_NEAREST_MIPMAP_LINEAR,
linear_mipmap_linear = c.GL_LINEAR_MIPMAP_LINEAR,
};
/// Magnification filter for textures.
pub const MagFilter = enum(c_int) {
nearest = c.GL_NEAREST,
linear = c.GL_LINEAR,
};
/// Texture coordinate wrapping mode.
pub const Wrap = enum(c_int) {
clamp_to_edge = c.GL_CLAMP_TO_EDGE,
clamp_to_border = c.GL_CLAMP_TO_BORDER,
mirrored_repeat = c.GL_MIRRORED_REPEAT,
repeat = c.GL_REPEAT,
};
/// Data type for texture images. /// Data type for texture images.
pub const DataType = enum(c_uint) { pub const DataType = enum(c_uint) {
UnsignedByte = c.GL_UNSIGNED_BYTE, UnsignedByte = c.GL_UNSIGNED_BYTE,

View File

@ -356,6 +356,10 @@ pub inline fn textureOptions(self: OpenGL) Texture.Options {
.format = .rgba, .format = .rgba,
.internal_format = .srgba, .internal_format = .srgba,
.target = .@"2D", .target = .@"2D",
.min_filter = .linear,
.mag_filter = .linear,
.wrap_s = .clamp_to_edge,
.wrap_t = .clamp_to_edge,
}; };
} }
@ -388,6 +392,16 @@ pub inline fn imageTextureOptions(
.format = format.toPixelFormat(), .format = format.toPixelFormat(),
.internal_format = if (srgb) .srgba else .rgba, .internal_format = if (srgb) .srgba else .rgba,
.target = .@"2D", .target = .@"2D",
// TODO: Generate mipmaps for image textures and use
// linear_mipmap_linear filtering so that they
// look good even when scaled way down.
.min_filter = .linear,
.mag_filter = .linear,
// TODO: Separate out background image options, use
// repeating coordinate modes so we don't have
// to do the modulus in the shader.
.wrap_s = .clamp_to_edge,
.wrap_t = .clamp_to_edge,
}; };
} }
@ -409,6 +423,10 @@ pub fn initAtlasTexture(
.format = format, .format = format,
.internal_format = internal_format, .internal_format = internal_format,
.target = .Rectangle, .target = .Rectangle,
.min_filter = .nearest,
.mag_filter = .nearest,
.wrap_s = .clamp_to_edge,
.wrap_t = .clamp_to_edge,
}, },
atlas.size, atlas.size,
atlas.size, atlas.size,

View File

@ -16,6 +16,10 @@ pub const Options = struct {
format: gl.Texture.Format, format: gl.Texture.Format,
internal_format: gl.Texture.InternalFormat, internal_format: gl.Texture.InternalFormat,
target: gl.Texture.Target, target: gl.Texture.Target,
min_filter: gl.Texture.MinFilter,
mag_filter: gl.Texture.MagFilter,
wrap_s: gl.Texture.Wrap,
wrap_t: gl.Texture.Wrap,
}; };
texture: gl.Texture, texture: gl.Texture,
@ -48,10 +52,10 @@ pub fn init(
{ {
const texbind = tex.bind(opts.target) catch return error.OpenGLFailed; const texbind = tex.bind(opts.target) catch return error.OpenGLFailed;
defer texbind.unbind(); defer texbind.unbind();
texbind.parameter(.WrapS, gl.c.GL_CLAMP_TO_EDGE) catch return error.OpenGLFailed; texbind.parameter(.WrapS, @intFromEnum(opts.wrap_s)) catch return error.OpenGLFailed;
texbind.parameter(.WrapT, gl.c.GL_CLAMP_TO_EDGE) catch return error.OpenGLFailed; texbind.parameter(.WrapT, @intFromEnum(opts.wrap_t)) catch return error.OpenGLFailed;
texbind.parameter(.MinFilter, gl.c.GL_LINEAR) catch return error.OpenGLFailed; texbind.parameter(.MinFilter, @intFromEnum(opts.min_filter)) catch return error.OpenGLFailed;
texbind.parameter(.MagFilter, gl.c.GL_LINEAR) catch return error.OpenGLFailed; texbind.parameter(.MagFilter, @intFromEnum(opts.mag_filter)) catch return error.OpenGLFailed;
texbind.image2D( texbind.image2D(
0, 0,
opts.internal_format, opts.internal_format,