mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2026-01-07 19:52:40 +01:00
Дальнейший рефакторинг
This commit is contained in:
parent
405112381d
commit
ebc975a162
@ -351,7 +351,7 @@
|
||||
url="https://raw.githubusercontent.com/IgorTimofeev/OpenComputers/master/lib/doubleBuffering.lua",
|
||||
type="Library",
|
||||
preloadFile=true,
|
||||
version=1.35,
|
||||
version=1.36,
|
||||
},
|
||||
{
|
||||
path="/lib/compressor.lua",
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
| ----- |
|
||||
| [О библиотеке](#О-библиотеке) |
|
||||
| [Установка](#Установка) |
|
||||
| [Свойства библиотеки](#Параметры-библиотеки) |
|
||||
| [Методы библиотеки](#Методы-библиотеки) |
|
||||
| [ buffer.getResolution](#buffergetresolution-int-width-int-height) |
|
||||
| [ buffer.setResolution](#buffersetresolution-width-height-) |
|
||||
| [ buffer.bindScreen](#bufferbindscreen-address-) |
|
||||
| [ buffer.bindGPU](#bufferbindgpu-address-) |
|
||||
@ -18,6 +18,8 @@
|
||||
| [ buffer.square](#buffersquare-x-y-width-height-background-foreground-symbol-transparency-) |
|
||||
| [ buffer.clear](#bufferclear-color-transparency-) |
|
||||
| [ buffer.text](#buffertext-x-y-color-text-transparency-) |
|
||||
| [ buffer.formattedText](#bufferformattedtext-x-y-text-) |
|
||||
| [ buffer.image](#bufferimage-x-y-picture-) |
|
||||
| [Методы полупиксельной отрисовки:](#Методы-полупиксельной-отрисовки) |
|
||||
| [ buffer.semiPixelSet](#buffersemipixelset-x-y-color-) |
|
||||
| [ buffer.semiPixelSquare](#buffersemipixelsquare-x-y-width-height-color-) |
|
||||
@ -35,7 +37,7 @@
|
||||
|
||||
О библиотеке
|
||||
======
|
||||
DoubleBuffering - низкоуровневая библиотека для эффективного использования ресурсов GPU и отрисовки содержимого экрана с предельной скоростью. К примеру, с ее помощью реализован наш игровой движок с динамическим освещением сцен, а также небольшая игра на алгоритме рейкастинга, выдающие более чем достойные значения FPS:
|
||||
DoubleBuffering - низкоуровневая библиотека для эффективного использования ресурсов GPU и отрисовки содержимого экрана с предельно возможной скоростью. К примеру, с ее помощью реализован наш игровой движок с динамическим освещением сцен, а также небольшая игра на алгоритме рейкастинга, выдающие более чем достойные значения FPS:
|
||||
|
||||

|
||||
|
||||
@ -53,6 +55,7 @@ DoubleBuffering - низкоуровневая библиотека для эф
|
||||
|
||||
Для получения данных о пикселях используются специальные методы, преобразующие экранные координаты в индексы экранного буфера и наоборот, подробнее об этом написано ниже в разделе "**Вспомогательные методы**".
|
||||
|
||||
Кроме того, библиотека не обращается ни к одной lua-таблице напрямую, заменяя их на переменные-аналоги и избегая при этом расчетов данных хеш-таблиц: к примеру, каждый метод GPU экранирован, и вместо gpu.setBackground используется GPUSetBackground(). При грамотной реализации такой подход колоссально увеличивает производительность, не нагружая при этом Lua GC.
|
||||
|
||||
Установка
|
||||
======
|
||||
@ -68,20 +71,13 @@ DoubleBuffering - низкоуровневая библиотека для эф
|
||||
|
||||
pastebin run vTM8nbSZ
|
||||
|
||||
Свойства библиотеки
|
||||
======
|
||||
|
||||
| Тип свойства | Свойство |Описание |
|
||||
| ------ | ------ | ------ |
|
||||
| *int* | buffer.**width**| Текущее разрешение буфера по ширине |
|
||||
| *int* | buffer.**height**| Текущее разрешение буфера по высоте |
|
||||
| *table* | buffer.**GPUProxy**| Указатель на proxy компонента видеокарты, с которой работает буфер |
|
||||
| *table* | buffer.**currentFrame**| Указатель на таблицу с пиксельными данными, содержащая то, что в данный момент отображено на экране. Она имеет структуру ```{ 0xFFFFFF, 0x000000, "Q", 0xFFFFFF, 0x000000, "W", ... }```, где первый элемент - цвет фона, второй - цвет текста, третий - символ. И так до конца размера буфера |
|
||||
| *table* | buffer.**newFrame**| Указатель на таблицу с пиксельными данными, содержащая то, что пользователь отрисовывает в него в данный момент. Структура аналогична предыдущей |
|
||||
|
||||
Основные методы
|
||||
======
|
||||
|
||||
buffer.**getResolution**(): *int* width, *int* height
|
||||
-----------------------------------------------------------
|
||||
Получить разрешение экранного буфера. Для удобства также имеются методы buffer.**getWidth**() и buffer.**getHeight**().
|
||||
|
||||
buffer.**setResolution**( width, height )
|
||||
-----------------------------------------------------------
|
||||
| Тип | Аргумент | Описание |
|
||||
@ -97,7 +93,7 @@ buffer.**bindScreen**( address )
|
||||
| ------ | ------ | ------ |
|
||||
| *string* | address | Адрес компонента экрана |
|
||||
|
||||
Связать используемую буфером видеокарту с указанным компонентом экрана. Содержимое буфера при этом будет заполнено черными пикселями с символом пробела.
|
||||
Связать используемую буфером видеокарту с указанным адресом компонента экрана. Содержимое буфера при этом будет очищено черными пикселями с символом пробела.
|
||||
|
||||
buffer.**bindGPU**( address )
|
||||
-----------------------------------------------------------
|
||||
@ -105,7 +101,11 @@ buffer.**bindGPU**( address )
|
||||
| ------ | ------ | ------ |
|
||||
| *string* | address | Адрес компонента видеокарты |
|
||||
|
||||
Изменить используемую буфером видеокарту на указанную. Содержимое буфера при этом будет заполнено черными пикселями с символом пробела.
|
||||
Изменить используемую буфером видеокарту на указанную. Содержимое буфера при этом будет очищено черными пикселями с символом пробела.
|
||||
|
||||
buffer.**getGPUProxy**( ): *table* GPUProxy
|
||||
-----------------------------------------------------------
|
||||
Получить указатель на proxy используемого буфером компонента видеокарты.
|
||||
|
||||
Методы отрисовки
|
||||
======
|
||||
@ -211,6 +211,16 @@ buffer.**text**( x, y, color, text, transparency )
|
||||
|
||||
Нарисовать текст указанного цвета поверх имеющихся пикселей. Цвет фона при этом остается прежним. Можно также указать опциональную прозрачность текста текста в диапазоне [0; 100].
|
||||
|
||||
buffer.**formattedText**( x, y, text )
|
||||
-----------------------------------------------------------
|
||||
| Тип | Аргумент | Описание |
|
||||
| ------ | ------ | ------ |
|
||||
| *int* | x | Координата текста по оси x |
|
||||
| *int* | y | Координата текста по оси y |
|
||||
| *string* | text | Текст |
|
||||
|
||||
Аналогичен методу buffer.**text**(), однако поддерживает цветовое форматирование. По умолчанию цвет текста имеет значение 0xFFFFFF, для его изменения используйте синтаксическую вставку вида **\#RRGGBB**. К примеру, "Hello world, **\#FF00FF**this is formatted text!".
|
||||
|
||||
buffer.**image**( x, y, picture )
|
||||
-----------------------------------------------------------
|
||||
| Тип | Аргумент | Описание |
|
||||
@ -294,7 +304,7 @@ buffer.**flush**( [width, height] )
|
||||
|
||||
Метод, устанавливающий разрешение экранного буфера равным указанному и заполняющий его черными пикселями с символом пробела. В отличие от buffer.**setResolution** не изменяет текущего разрешения GPU. Если опциональные аргументы не указаны, то размер буфера становится эквивалентным текущему разрешению GPU.
|
||||
|
||||
buffer.**getIndexByCoordinates**( x, y ): int index
|
||||
buffer.**getIndex*( x, y ): int index
|
||||
-----------------------------------------------------------
|
||||
| Тип | Аргумент | Описание |
|
||||
| ------ | ------ | ------ |
|
||||
@ -303,7 +313,7 @@ buffer.**getIndexByCoordinates**( x, y ): int index
|
||||
|
||||
Метод, преобразующий экранные координаты в индекс экраннного буфера. К примеру, пиксель 2x1 имеет индекс буфера 4, а пиксель 3x1 имеет индекс буфера 7.
|
||||
|
||||
buffer.**getCoordinatesByIndex**( index ): int x, int y
|
||||
buffer.**getCoordinates**( index ): int x, int y
|
||||
-----------------------------------------------------------
|
||||
| Тип | Аргумент | Описание |
|
||||
| ------ | ------ | ------ |
|
||||
@ -330,17 +340,20 @@ buffer.**rawGet**( index ): int background, int foreground, char symbol
|
||||
|
||||
Метод, возвращающий соответствующие значения цветов и символа пикселя с указанным индексом.
|
||||
|
||||
Практический пример #1
|
||||
Практический пример
|
||||
======
|
||||
|
||||
```lua
|
||||
-- Подключаем библиотеку
|
||||
-- Подключаем библиотеки
|
||||
local buffer = require("doubleBuffering")
|
||||
local image = require("image")
|
||||
|
||||
-- Загружаем и рисуем изображение с лукошком с малиной
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
-- Загружаем и рисуем изображение
|
||||
buffer.image(1, 1, image.load("/MineOS/Pictures/Raspberry.pic"))
|
||||
-- Заполняем буфер черным цветом с прозрачностью 60%, чтобы малина на фоне была чуть темнее
|
||||
buffer.clear(0x0, 60)
|
||||
-- Заполняем буфер черным цветом с прозрачностью 60%, чтобы изображение было чуть темнее
|
||||
buffer.clear(0x0, 0.6)
|
||||
|
||||
-- Рисуем 10 квадратиков, заполненных случайным цветом
|
||||
local x, y, xStep, yStep = 2, 2, 4, 2
|
||||
|
||||
@ -14,7 +14,7 @@ local drawLimitX1, drawLimitX2, drawLimitY1, drawLimitY2
|
||||
|
||||
local GPUProxy, GPUProxyGetResolution, GPUProxySetResolution, GPUProxyBind, GPUProxyGetBackground, GPUProxyGetForeground, GPUProxySetBackground, GPUProxySetForeground, GPUProxyGet, GPUProxySet
|
||||
local mathCeil, mathFloor, mathModf, mathAbs = math.ceil, math.floor, math.modf, math.abs
|
||||
local tableInsert = table.insert
|
||||
local tableInsert, tableConcat = table.insert, table.concat
|
||||
local colorBlend = color.blend
|
||||
local unicodeLen, unicodeSub = unicode.len, unicode.sub
|
||||
|
||||
@ -554,64 +554,67 @@ local function info(...)
|
||||
GPUProxySetBackground(0x0)
|
||||
GPUProxySetForeground(0xFFFFFF)
|
||||
GPUProxyFill(1, bufferHeight, bufferWidth, 1, " ")
|
||||
GPUProxySet(2, bufferHeight, table.concat(text, ", "))
|
||||
GPUProxySet(2, bufferHeight, tableConcat(text, ", "))
|
||||
GPUProxySetBackground(b)
|
||||
GPUProxySetForeground(f)
|
||||
end
|
||||
|
||||
local function calculateDifference(index, indexPlus1, indexPlus2)
|
||||
local somethingIsChanged =
|
||||
currentFrame[index] ~= newFrame[index] or
|
||||
currentFrame[indexPlus1] ~= newFrame[indexPlus1] or
|
||||
currentFrame[indexPlus2] ~= newFrame[indexPlus2]
|
||||
|
||||
currentFrame[index] = newFrame[index]
|
||||
currentFrame[indexPlus1] = newFrame[indexPlus1]
|
||||
currentFrame[indexPlus2] = newFrame[indexPlus2]
|
||||
|
||||
return somethingIsChanged
|
||||
end
|
||||
|
||||
local function draw(force)
|
||||
-- local oldClock = os.clock()
|
||||
local changes, index, indexStepOnEveryLine, indexPlus1, indexPlus2, sameCharArray, x, xCharCheck, indexCharCheck, indexCharCheckPlus1, indexCharCheckPlus2, currentForeground = {}, getIndex(drawLimitX1, drawLimitY1), (bufferWidth - drawLimitX2 + drawLimitX1 - 1) * 3
|
||||
local changes, index, indexStepOnEveryLine, indexPlus1, indexPlus2, equalChars, x, charX, charIndex, charIndexPlus1, charIndexPlus2, currentForeground = {}, getIndex(drawLimitX1, drawLimitY1), (bufferWidth - drawLimitX2 + drawLimitX1 - 1) * 3
|
||||
|
||||
for y = drawLimitY1, drawLimitY2 do
|
||||
x = drawLimitX1
|
||||
|
||||
while x <= drawLimitX2 do
|
||||
indexPlus1, indexPlus2 = index + 1, index + 2
|
||||
|
||||
if calculateDifference(index, indexPlus1, indexPlus2) or force then
|
||||
sameCharArray = { currentFrame[indexPlus2] }
|
||||
xCharCheck, indexCharCheck = x + 1, index + 3
|
||||
|
||||
while xCharCheck <= drawLimitX2 do
|
||||
indexCharCheckPlus1, indexCharCheckPlus2 = indexCharCheck + 1, indexCharCheck + 2
|
||||
-- Determine if some pixel data was changed (or if <force> argument was passed)
|
||||
if
|
||||
currentFrame[index] ~= newFrame[index] or
|
||||
currentFrame[indexPlus1] ~= newFrame[indexPlus1] or
|
||||
currentFrame[indexPlus2] ~= newFrame[indexPlus2] or
|
||||
force
|
||||
then
|
||||
-- Make pixel at both frames equal
|
||||
currentFrame[index] = newFrame[index]
|
||||
currentFrame[indexPlus1] = newFrame[indexPlus1]
|
||||
currentFrame[indexPlus2] = newFrame[indexPlus2]
|
||||
|
||||
-- Look for pixels with equal chars from right of current pixel
|
||||
equalChars = {currentFrame[indexPlus2]}
|
||||
charX, charIndex = x + 1, index + 3
|
||||
while charX <= drawLimitX2 do
|
||||
charIndexPlus1, charIndexPlus2 = charIndex + 1, charIndex + 2
|
||||
-- Pixels becomes equal only if they have same background and (whitespace char or same foreground)
|
||||
if
|
||||
currentFrame[index] == newFrame[indexCharCheck] and
|
||||
currentFrame[index] == newFrame[charIndex] and
|
||||
(
|
||||
newFrame[indexCharCheckPlus2] == " " or
|
||||
currentFrame[indexPlus1] == newFrame[indexCharCheckPlus1]
|
||||
newFrame[charIndexPlus2] == " " or
|
||||
currentFrame[indexPlus1] == newFrame[charIndexPlus1]
|
||||
)
|
||||
then
|
||||
calculateDifference(indexCharCheck, indexCharCheckPlus1, indexCharCheckPlus2)
|
||||
tableInsert(sameCharArray, currentFrame[indexCharCheckPlus2])
|
||||
-- Make pixel at both frames equal
|
||||
currentFrame[charIndex] = newFrame[charIndex]
|
||||
currentFrame[charIndexPlus1] = newFrame[charIndexPlus1]
|
||||
currentFrame[charIndexPlus2] = newFrame[charIndexPlus2]
|
||||
|
||||
tableInsert(equalChars, currentFrame[charIndexPlus2])
|
||||
else
|
||||
break
|
||||
end
|
||||
|
||||
indexCharCheck, xCharCheck = indexCharCheck + 3, xCharCheck + 1
|
||||
charIndex, charX = charIndex + 3, charX + 1
|
||||
end
|
||||
|
||||
-- Group pixels that need to be drawn by background and foreground
|
||||
changes[currentFrame[index]] = changes[currentFrame[index]] or {}
|
||||
changes[currentFrame[index]][currentFrame[indexPlus1]] = changes[currentFrame[index]][currentFrame[indexPlus1]] or {}
|
||||
|
||||
|
||||
tableInsert(changes[currentFrame[index]][currentFrame[indexPlus1]], x)
|
||||
tableInsert(changes[currentFrame[index]][currentFrame[indexPlus1]], y)
|
||||
tableInsert(changes[currentFrame[index]][currentFrame[indexPlus1]], table.concat(sameCharArray))
|
||||
tableInsert(changes[currentFrame[index]][currentFrame[indexPlus1]], tableConcat(equalChars))
|
||||
|
||||
x, index = x + #sameCharArray - 1, index + #sameCharArray * 3 - 3
|
||||
x, index = x + #equalChars - 1, index + (#equalChars - 1) * 3
|
||||
end
|
||||
|
||||
x, index = x + 1, index + 3
|
||||
@ -620,17 +623,18 @@ local function draw(force)
|
||||
index = index + indexStepOnEveryLine
|
||||
end
|
||||
|
||||
for background in pairs(changes) do
|
||||
-- Draw grouped pixels on screen
|
||||
for background, foregrounds in pairs(changes) do
|
||||
GPUProxySetBackground(background)
|
||||
|
||||
for foreground in pairs(changes[background]) do
|
||||
for foreground, pixels in pairs(foregrounds) do
|
||||
if currentForeground ~= foreground then
|
||||
GPUProxySetForeground(foreground)
|
||||
currentForeground = foreground
|
||||
end
|
||||
|
||||
for i = 1, #changes[background][foreground], 3 do
|
||||
GPUProxySet(changes[background][foreground][i], changes[background][foreground][i + 1], changes[background][foreground][i + 2])
|
||||
for i = 1, #pixels, 3 do
|
||||
GPUProxySet(pixels[i], pixels[i + 1], pixels[i + 2])
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -687,17 +691,4 @@ return {
|
||||
scrollBar = scrollBar,
|
||||
horizontalScrollBar = horizontalScrollBar,
|
||||
customImage = customImage,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user