diff --git a/TextureFilters.go b/TextureFilters.go new file mode 100644 index 00000000..debcfda1 --- /dev/null +++ b/TextureFilters.go @@ -0,0 +1,11 @@ +package giu + +// Texture filtering types. +const ( + TextureFilterNearest = iota + TextureFilterLinear + TextureFilterNearestMipmapNearest + TextureFilterLinearMipmapNearest + TextureFilterNearestMipmapLinear + TextureFilterLinearMipmapLinear +) diff --git a/examples/texturefiltering/gopher-sprite.png b/examples/texturefiltering/gopher-sprite.png new file mode 100644 index 00000000..fb24a8ab Binary files /dev/null and b/examples/texturefiltering/gopher-sprite.png differ diff --git a/examples/texturefiltering/gopher.png b/examples/texturefiltering/gopher.png new file mode 100644 index 00000000..0587e709 Binary files /dev/null and b/examples/texturefiltering/gopher.png differ diff --git a/examples/texturefiltering/texturefiltering.go b/examples/texturefiltering/texturefiltering.go new file mode 100644 index 00000000..cfd49721 --- /dev/null +++ b/examples/texturefiltering/texturefiltering.go @@ -0,0 +1,93 @@ +package main + +import ( + _ "image/jpeg" + _ "image/png" + + g "github.com/AllenDang/giu" +) + +var ( + spriteTexture *g.Texture + largeTexture *g.Texture +) + +func loop() { + g.SingleWindow("load image", g.Layout{ + g.Group(g.Layout{ + g.Label("15x20 pixel image"), + g.Line( + g.Group(g.Layout{ + g.Label("50%"), + g.Image(spriteTexture, 8, 10), + }), + g.Group(g.Layout{ + g.Label("100%"), + g.Image(spriteTexture, 15, 20), + }), + g.Group(g.Layout{ + g.Label("800%"), + g.Image(spriteTexture, 120, 160), + }), + ), + }), + g.Group(g.Layout{ + g.Label("215x140 image"), + g.Line( + g.Group(g.Layout{ + g.Label("50%"), + g.Image(largeTexture, 215/2, 140/2), + }), + g.Group(g.Layout{ + g.Label("100%"), + g.Image(largeTexture, 215, 140), + }), + g.Group(g.Layout{ + g.Label("200%"), + g.Image(largeTexture, 215*2, 140*2), + }), + ), + }), + g.Line( + g.Button("Minify Filter Nearest", func() { + g.Context.GetRenderer().SetTextureMinFilter(g.TextureFilterNearest) + }), + g.Button("Minify Filter Linear", func() { + g.Context.GetRenderer().SetTextureMinFilter(g.TextureFilterLinear) + }), + /*g.Button("Nearest Mipmap Nearest", func() { + g.Context.GetRenderer().SetTextureMinFilter(g.TextureFilterNearestMipmapNearest) + }), + g.Button("Linear Mipmap Nearest", func() { + g.Context.GetRenderer().SetTextureMinFilter(g.TextureFilterLinearMipmapNearest) + }), + g.Button("Nearest Mipmap Linear", func() { + g.Context.GetRenderer().SetTextureMinFilter(g.TextureFilterNearestMipmapLinear) + }), + g.Button("Linear Mipmap Linear", func() { + g.Context.GetRenderer().SetTextureMinFilter(g.TextureFilterLinearMipmapLinear) + }),*/ + ), + g.Line( + g.Button("Magnify Filter Nearest", func() { + g.Context.GetRenderer().SetTextureMagFilter(g.TextureFilterNearest) + }), + g.Button("Magnify Filter Linear", func() { + g.Context.GetRenderer().SetTextureMagFilter(g.TextureFilterLinear) + }), + ), + }) +} + +func main() { + wnd := g.NewMasterWindow("Texture Filtering", 800, 600, g.MasterWindowFlagsNotResizable, nil) + + spriteImg, _ := g.LoadImage("gopher-sprite.png") + largeImg, _ := g.LoadImage("gopher.png") + go func() { + spriteTexture, _ = g.NewTextureFromRgba(spriteImg) + largeTexture, _ = g.NewTextureFromRgba(largeImg) + }() + + wnd.Main(loop) +} diff --git a/imgui/RendererInterface.go b/imgui/RendererInterface.go index 909ee2ac..f44cd075 100644 --- a/imgui/RendererInterface.go +++ b/imgui/RendererInterface.go @@ -8,6 +8,10 @@ type Renderer interface { PreRender(clearColor [4]float32) // Render draws the provided imgui draw data. Render(displaySize [2]float32, framebufferSize [2]float32, drawData DrawData) + // Sets the texture minifying filter. + SetTextureMinFilter(min uint) error + // Sets the texture magnifying filter. + SetTextureMagFilter(mag uint) error // Load image and return the TextureID LoadImage(image *image.RGBA) (TextureID, error) // Release image diff --git a/imgui/RendererOpenGL3.go b/imgui/RendererOpenGL3.go index 6d679ba4..20f82e3b 100644 --- a/imgui/RendererOpenGL3.go +++ b/imgui/RendererOpenGL3.go @@ -28,9 +28,21 @@ type OpenGL3 struct { vboHandle uint32 elementsHandle uint32 - contentScale float32 + contentScale float32 + textureMinFilter int32 + textureMagFilter int32 } +// Texture filtering types. +const ( + textureFilterNearest = iota + textureFilterLinear + textureFilterNearestMipmapNearest + textureFilterLinearMipmapNearest + textureFilterNearestMipmapLinear + textureFilterLinearMipmapLinear +) + // NewOpenGL3 attempts to initialize a renderer. // An OpenGL context has to be established before calling this function. func NewOpenGL3(io IO, contentScale float32) (*OpenGL3, error) { @@ -40,9 +52,11 @@ func NewOpenGL3(io IO, contentScale float32) (*OpenGL3, error) { } renderer := &OpenGL3{ - imguiIO: io, - glslVersion: "#version 150", - contentScale: contentScale, + imguiIO: io, + glslVersion: "#version 150", + contentScale: contentScale, + textureMinFilter: gl.LINEAR, + textureMagFilter: gl.LINEAR, } renderer.createDeviceObjects() return renderer, nil @@ -176,6 +190,8 @@ func (renderer *OpenGL3) Render(displaySize [2]float32, framebufferSize [2]float gl.Uniform1i(renderer.attribLocationImageType, int32(imageType)) gl.BindTexture(gl.TEXTURE_2D, uint32(cmd.TextureID())) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, renderer.textureMinFilter) // minification filter + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, renderer.textureMagFilter) // magnification filter clipRect := cmd.ClipRect() gl.Scissor(int32(clipRect.X), int32(fbHeight)-int32(clipRect.W), int32(clipRect.Z-clipRect.X), int32(clipRect.W-clipRect.Y)) gl.DrawElements(gl.TRIANGLES, int32(cmd.ElementCount()), uint32(drawType), unsafe.Pointer(indexBufferOffset)) @@ -384,6 +400,40 @@ func (renderer *OpenGL3) invalidateDeviceObjects() { } } +// SetTextureMinFilter sets the minifying function for texture filtering. +func (renderer *OpenGL3) SetTextureMinFilter(min uint) error { + switch min { + case textureFilterNearest: + renderer.textureMinFilter = gl.NEAREST + case textureFilterLinear: + renderer.textureMinFilter = gl.LINEAR + case textureFilterNearestMipmapNearest: + renderer.textureMinFilter = gl.NEAREST_MIPMAP_NEAREST + case textureFilterLinearMipmapNearest: + renderer.textureMinFilter = gl.LINEAR_MIPMAP_NEAREST + case textureFilterNearestMipmapLinear: + renderer.textureMinFilter = gl.NEAREST_MIPMAP_LINEAR + case textureFilterLinearMipmapLinear: + renderer.textureMinFilter = gl.LINEAR_MIPMAP_LINEAR + default: + return fmt.Errorf("invalid minifying filter") + } + return nil +} + +// SetTextureMagFilter sets the magnifying function for texture filtering. +func (renderer *OpenGL3) SetTextureMagFilter(mag uint) error { + switch mag { + case textureFilterNearest: + renderer.textureMagFilter = gl.NEAREST + case textureFilterLinear: + renderer.textureMagFilter = gl.LINEAR + default: + return fmt.Errorf("invalid magnifying filter") + } + return nil +} + // Load image and return the TextureID func (renderer *OpenGL3) LoadImage(image *image.RGBA) (TextureID, error) { texture, err := renderer.createImageTexture(image)