mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 11:09:20 +01:00
Generate and use mipmaps for screen textures
This commit is contained in:
parent
acb1374140
commit
5e7777bd4c
@ -53,4 +53,9 @@ ocelot {
|
|||||||
# Otherwise, content will be shown only in windows
|
# Otherwise, content will be shown only in windows
|
||||||
renderScreenDataOnNodes: true
|
renderScreenDataOnNodes: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render {
|
||||||
|
# Whether mipmap scaling is enabled for screen windows (when shrinking).
|
||||||
|
screenWindowMipmap: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,8 @@ class Settings(val config: Config) extends SettingsData {
|
|||||||
saveOnExit = config.getBooleanOrElse("ocelot.workspace.saveOnExit", default = true)
|
saveOnExit = config.getBooleanOrElse("ocelot.workspace.saveOnExit", default = true)
|
||||||
openLastWorkspace = config.getBooleanOrElse("ocelot.workspace.openLastWorkspace", default = true)
|
openLastWorkspace = config.getBooleanOrElse("ocelot.workspace.openLastWorkspace", default = true)
|
||||||
renderScreenDataOnNodes = config.getBooleanOrElse("ocelot.workspace.renderScreenDataOnNodes", default = true)
|
renderScreenDataOnNodes = config.getBooleanOrElse("ocelot.workspace.renderScreenDataOnNodes", default = true)
|
||||||
|
|
||||||
|
screenWindowMipmap = config.getBooleanOrElse("ocelot.render.screenWindowMipmap", default = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
object Settings extends Logging {
|
object Settings extends Logging {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package ocelot.desktop.graphics
|
|||||||
import ocelot.desktop.color.{Color, RGBAColorNorm}
|
import ocelot.desktop.color.{Color, RGBAColorNorm}
|
||||||
import ocelot.desktop.geometry.{Rect2D, Size2D, Transform2D, Vector2D}
|
import ocelot.desktop.geometry.{Rect2D, Size2D, Transform2D, Vector2D}
|
||||||
import ocelot.desktop.graphics.IconSource.Animation
|
import ocelot.desktop.graphics.IconSource.Animation
|
||||||
|
import ocelot.desktop.graphics.Texture.MinFilteringMode
|
||||||
import ocelot.desktop.graphics.mesh.{Mesh2D, MeshInstance2D, MeshVertex2D}
|
import ocelot.desktop.graphics.mesh.{Mesh2D, MeshInstance2D, MeshVertex2D}
|
||||||
import ocelot.desktop.graphics.render.InstanceRenderer
|
import ocelot.desktop.graphics.render.InstanceRenderer
|
||||||
import ocelot.desktop.ui.UiHandler
|
import ocelot.desktop.ui.UiHandler
|
||||||
@ -145,11 +146,19 @@ class Graphics(private var width: Int, private var height: Int, private var scal
|
|||||||
flush(mainTexture = viewport.textureColor)
|
flush(mainTexture = viewport.textureColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
def blitScreenViewport(viewport: ScreenViewport, bounds: Rect2D, alpha: Float = 1.0f): Unit = {
|
def blitScreenViewport(
|
||||||
|
viewport: ScreenViewport,
|
||||||
|
bounds: Rect2D,
|
||||||
|
filteringMode: MinFilteringMode = MinFilteringMode.Nearest,
|
||||||
|
alpha: Float = 1.0f
|
||||||
|
): Unit = {
|
||||||
flush()
|
flush()
|
||||||
foreground = RGBAColorNorm(1, 1, 1, alpha)
|
foreground = RGBAColorNorm(1, 1, 1, alpha)
|
||||||
spriteRect = Rect2D(0, 1f, 1f, -1f)
|
spriteRect = Rect2D(0, 1f, 1f, -1f)
|
||||||
_rect(bounds.x, bounds.y, bounds.w, bounds.h, fixUV = false)
|
_rect(bounds.x, bounds.y, bounds.w, bounds.h, fixUV = false)
|
||||||
|
|
||||||
|
viewport.texture.setMinFilter(filteringMode)
|
||||||
|
|
||||||
flush(mainTexture = viewport.texture)
|
flush(mainTexture = viewport.texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,8 @@ class ScreenViewport(graphics: Graphics, private var _width: Int, private var _h
|
|||||||
private var _foreground: RGBAColorNorm = RGBAColorNorm(0f, 0f, 0f)
|
private var _foreground: RGBAColorNorm = RGBAColorNorm(0f, 0f, 0f)
|
||||||
private var _background: RGBAColorNorm = RGBAColorNorm(1f, 1f, 1f)
|
private var _background: RGBAColorNorm = RGBAColorNorm(1f, 1f, 1f)
|
||||||
|
|
||||||
|
private var mipmapDirty = false
|
||||||
|
|
||||||
override def freeResource(): Unit = {
|
override def freeResource(): Unit = {
|
||||||
super.freeResource()
|
super.freeResource()
|
||||||
|
|
||||||
@ -110,6 +112,8 @@ class ScreenViewport(graphics: Graphics, private var _width: Int, private var _h
|
|||||||
Spritesheet.texture.bind()
|
Spritesheet.texture.bind()
|
||||||
_font.texture.bind(1)
|
_font.texture.bind(1)
|
||||||
renderer.flush()
|
renderer.flush()
|
||||||
|
|
||||||
|
mipmapDirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
def renderWith(f: => Unit): Unit = {
|
def renderWith(f: => Unit): Unit = {
|
||||||
@ -121,4 +125,11 @@ class ScreenViewport(graphics: Graphics, private var _width: Int, private var _h
|
|||||||
flush()
|
flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def generateMipmap(): Unit = {
|
||||||
|
if (mipmapDirty) {
|
||||||
|
texture.generateMipmap()
|
||||||
|
mipmapDirty = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package ocelot.desktop.graphics
|
package ocelot.desktop.graphics
|
||||||
|
|
||||||
|
import ocelot.desktop.graphics.Texture.MinFilteringMode
|
||||||
import ocelot.desktop.util.{Logging, Resource}
|
import ocelot.desktop.util.{Logging, Resource}
|
||||||
import org.lwjgl.BufferUtils
|
import org.lwjgl.BufferUtils
|
||||||
import org.lwjgl.opengl._
|
import org.lwjgl.opengl._
|
||||||
@ -7,7 +8,7 @@ import org.lwjgl.opengl._
|
|||||||
import java.awt.image.BufferedImage
|
import java.awt.image.BufferedImage
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
class Texture extends Logging with Resource {
|
class Texture() extends Logging with Resource {
|
||||||
val texture: Int = GL11.glGenTextures()
|
val texture: Int = GL11.glGenTextures()
|
||||||
|
|
||||||
bind()
|
bind()
|
||||||
@ -70,8 +71,30 @@ class Texture extends Logging with Resource {
|
|||||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture)
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def setMinFilter(filter: MinFilteringMode): Unit = {
|
||||||
|
bind()
|
||||||
|
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter.glValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
def generateMipmap(): Unit = {
|
||||||
|
bind()
|
||||||
|
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D)
|
||||||
|
}
|
||||||
|
|
||||||
override def freeResource(): Unit = {
|
override def freeResource(): Unit = {
|
||||||
super.freeResource()
|
super.freeResource()
|
||||||
GL11.glDeleteTextures(texture)
|
GL11.glDeleteTextures(texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Texture {
|
||||||
|
class MinFilteringMode private(private[Texture] val glValue: Int, val needsMipmap: Boolean)
|
||||||
|
|
||||||
|
object MinFilteringMode {
|
||||||
|
val Nearest = new MinFilteringMode(GL11.GL_NEAREST, false)
|
||||||
|
val NearestMipmapNearest = new MinFilteringMode(GL11.GL_NEAREST_MIPMAP_NEAREST, true)
|
||||||
|
val NearestMipmapLinear = new MinFilteringMode(GL11.GL_NEAREST_MIPMAP_LINEAR, true)
|
||||||
|
val LinearMipmapNearest = new MinFilteringMode(GL11.GL_LINEAR_MIPMAP_NEAREST, true)
|
||||||
|
val LinearMipmapLinear = new MinFilteringMode(GL11.GL_LINEAR_MIPMAP_LINEAR, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package ocelot.desktop.node.nodes
|
|||||||
|
|
||||||
import ocelot.desktop.color.{Color, IntColor}
|
import ocelot.desktop.color.{Color, IntColor}
|
||||||
import ocelot.desktop.geometry.{Rect2D, Size2D}
|
import ocelot.desktop.geometry.{Rect2D, Size2D}
|
||||||
|
import ocelot.desktop.graphics.Texture.MinFilteringMode
|
||||||
import ocelot.desktop.graphics.{Graphics, IconSource, ScreenViewport}
|
import ocelot.desktop.graphics.{Graphics, IconSource, ScreenViewport}
|
||||||
import ocelot.desktop.node.Node.{HighlightThickness, NoHighlightSize, Size}
|
import ocelot.desktop.node.Node.{HighlightThickness, NoHighlightSize, Size}
|
||||||
import ocelot.desktop.node.nodes.ScreenNode.{FontHeight, FontWidth, Margin}
|
import ocelot.desktop.node.nodes.ScreenNode.{FontHeight, FontWidth, Margin}
|
||||||
@ -116,44 +117,55 @@ class ScreenNode(val screen: Screen)
|
|||||||
super.setupContextMenu(menu, event)
|
super.setupContextMenu(menu, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def drawScreenTexture(): Unit = {
|
private def drawScreenTexture(needsMipmap: Boolean): Unit = {
|
||||||
if (bufferRendered) return
|
if (!bufferRendered) {
|
||||||
|
viewport.renderWith {
|
||||||
|
val width = (screen.getWidth * FontWidth).toInt
|
||||||
|
val height = (screen.getHeight * FontHeight).toInt
|
||||||
|
|
||||||
viewport.renderWith {
|
viewport.resize(width, height)
|
||||||
val width = (screen.getWidth * FontWidth).toInt
|
|
||||||
val height = (screen.getHeight * FontHeight).toInt
|
|
||||||
|
|
||||||
viewport.resize(width, height)
|
var color: Short = 0
|
||||||
|
|
||||||
var color: Short = 0
|
for (y <- 0 until screen.getHeight) {
|
||||||
|
for (x <- 0 until screen.getWidth) {
|
||||||
|
if (x == 0 || viewport.font.charWidth(screen.data.buffer(y)(x - 1)) != 16) {
|
||||||
|
color = screen.data.color(y)(x)
|
||||||
|
|
||||||
for (y <- 0 until screen.getHeight) {
|
viewport.background = IntColor(PackedColor.unpackBackground(color, screen.data.format))
|
||||||
for (x <- 0 until screen.getWidth) {
|
viewport.foreground = IntColor(PackedColor.unpackForeground(color, screen.data.format))
|
||||||
if (x == 0 || viewport.font.charWidth(screen.data.buffer(y)(x - 1)) != 16) {
|
|
||||||
color = screen.data.color(y)(x)
|
|
||||||
|
|
||||||
viewport.background = IntColor(PackedColor.unpackBackground(color, screen.data.format))
|
viewport.char(x * FontWidth, y * FontHeight, screen.data.buffer(y)(x))
|
||||||
viewport.foreground = IntColor(PackedColor.unpackForeground(color, screen.data.format))
|
}
|
||||||
|
|
||||||
viewport.char(x * FontWidth, y * FontHeight, screen.data.buffer(y)(x))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferRendered = true
|
bufferRendered = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needsMipmap) {
|
||||||
|
viewport.generateMipmap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def drawScreenData(g: Graphics, startX: Float, startY: Float, scaleX: Float, scaleY: Float): Unit = {
|
def drawScreenData(
|
||||||
|
g: Graphics,
|
||||||
|
startX: Float,
|
||||||
|
startY: Float,
|
||||||
|
scaleX: Float,
|
||||||
|
scaleY: Float,
|
||||||
|
filteringMode: MinFilteringMode
|
||||||
|
): Unit = {
|
||||||
g.save()
|
g.save()
|
||||||
g.scale(scaleX, scaleY)
|
g.scale(scaleX, scaleY)
|
||||||
|
|
||||||
val startXScaled = startX / scaleX
|
val startXScaled = startX / scaleX
|
||||||
val startYScaled = startY / scaleY
|
val startYScaled = startY / scaleY
|
||||||
|
|
||||||
drawScreenTexture()
|
drawScreenTexture(filteringMode.needsMipmap)
|
||||||
val bounds = Rect2D(startXScaled, startYScaled, viewport.width, viewport.height)
|
val bounds = Rect2D(startXScaled, startYScaled, viewport.width, viewport.height)
|
||||||
g.blitScreenViewport(viewport, bounds)
|
g.blitScreenViewport(viewport, bounds, filteringMode = filteringMode)
|
||||||
|
|
||||||
g.restore()
|
g.restore()
|
||||||
}
|
}
|
||||||
@ -351,7 +363,8 @@ class ScreenNode(val screen: Screen)
|
|||||||
virtualScreenBounds.x + virtualScreenBounds.w / 2 - (pixelDataSize.width * scale) / 2,
|
virtualScreenBounds.x + virtualScreenBounds.w / 2 - (pixelDataSize.width * scale) / 2,
|
||||||
virtualScreenBounds.y + virtualScreenBounds.h / 2 - (pixelDataSize.height * scale) / 2,
|
virtualScreenBounds.y + virtualScreenBounds.h / 2 - (pixelDataSize.height * scale) / 2,
|
||||||
scale,
|
scale,
|
||||||
scale
|
scale,
|
||||||
|
MinFilteringMode.NearestMipmapNearest
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Drawing simple overlay otherwise
|
// Drawing simple overlay otherwise
|
||||||
|
|||||||
@ -68,6 +68,15 @@ class UISettingsTab extends SettingsTab {
|
|||||||
}
|
}
|
||||||
}, Padding2D(bottom = 8))
|
}, Padding2D(bottom = 8))
|
||||||
|
|
||||||
|
children :+= new PaddingBox(new Checkbox("Enable mipmaps for screen windows",
|
||||||
|
initialValue = Settings.get.screenWindowMipmap) {
|
||||||
|
override def minimumSize: Size2D = Size2D(512, 24)
|
||||||
|
|
||||||
|
override def onValueChanged(value: Boolean): Unit = {
|
||||||
|
Settings.get.screenWindowMipmap = value
|
||||||
|
}
|
||||||
|
}, Padding2D(bottom = 8))
|
||||||
|
|
||||||
children :+= new PaddingBox(new Slider((Settings.get.scaleFactor - 1) / 2, "Interface scale", 5) {
|
children :+= new PaddingBox(new Slider((Settings.get.scaleFactor - 1) / 2, "Interface scale", 5) {
|
||||||
override def minimumSize: Size2D = Size2D(512, 24)
|
override def minimumSize: Size2D = Size2D(512, 24)
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,8 @@ class SettingsData {
|
|||||||
var openLastWorkspace: Boolean = true
|
var openLastWorkspace: Boolean = true
|
||||||
var renderScreenDataOnNodes: Boolean = true
|
var renderScreenDataOnNodes: Boolean = true
|
||||||
|
|
||||||
|
var screenWindowMipmap: Boolean = true
|
||||||
|
|
||||||
private val mirror = universe.runtimeMirror(getClass.getClassLoader).reflect(this)
|
private val mirror = universe.runtimeMirror(getClass.getClassLoader).reflect(this)
|
||||||
|
|
||||||
def updateWith(data: SettingsData): Unit = {
|
def updateWith(data: SettingsData): Unit = {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import ocelot.desktop.audio.SoundSource
|
|||||||
import ocelot.desktop.color.RGBAColor
|
import ocelot.desktop.color.RGBAColor
|
||||||
import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D}
|
import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D}
|
||||||
import ocelot.desktop.graphics.Graphics
|
import ocelot.desktop.graphics.Graphics
|
||||||
|
import ocelot.desktop.graphics.Texture.MinFilteringMode
|
||||||
import ocelot.desktop.node.nodes.ScreenNode
|
import ocelot.desktop.node.nodes.ScreenNode
|
||||||
import ocelot.desktop.node.nodes.ScreenNode.{FontHeight, FontWidth}
|
import ocelot.desktop.node.nodes.ScreenNode.{FontHeight, FontWidth}
|
||||||
import ocelot.desktop.ui.UiHandler
|
import ocelot.desktop.ui.UiHandler
|
||||||
@ -12,7 +13,7 @@ import ocelot.desktop.ui.event.{DragEvent, KeyEvent, MouseEvent, ScrollEvent}
|
|||||||
import ocelot.desktop.ui.widget.window.BasicWindow
|
import ocelot.desktop.ui.widget.window.BasicWindow
|
||||||
import ocelot.desktop.util.{DrawUtils, Logging}
|
import ocelot.desktop.util.{DrawUtils, Logging}
|
||||||
import ocelot.desktop.windows.ScreenWindow._
|
import ocelot.desktop.windows.ScreenWindow._
|
||||||
import ocelot.desktop.{ColorScheme, OcelotDesktop}
|
import ocelot.desktop.{ColorScheme, OcelotDesktop, Settings}
|
||||||
import org.apache.commons.lang3.StringUtils
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.lwjgl.input.Keyboard
|
import org.lwjgl.input.Keyboard
|
||||||
import totoro.ocelot.brain.entity.Screen
|
import totoro.ocelot.brain.entity.Screen
|
||||||
@ -254,7 +255,12 @@ class ScreenWindow(screenNode: ScreenNode) extends BasicWindow with Logging {
|
|||||||
startX,
|
startX,
|
||||||
startY,
|
startY,
|
||||||
scaleX,
|
scaleX,
|
||||||
scaleY
|
scaleY,
|
||||||
|
if (Settings.get.screenWindowMipmap) {
|
||||||
|
MinFilteringMode.LinearMipmapLinear
|
||||||
|
} else {
|
||||||
|
MinFilteringMode.Nearest
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user