mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-24 04:52:48 +01:00
388 lines
26 KiB
Markdown
388 lines
26 KiB
Markdown
| Содержание |
|
||
| ----- |
|
||
| [О библиотеке](#О-библиотеке) |
|
||
| [Установка](#Установка) |
|
||
| [Методы библиотеки](#Методы-библиотеки) |
|
||
| [ buffer.getResolution](#buffergetresolution-int-width-int-height) |
|
||
| [ buffer.setResolution](#buffersetresolution-width-height-) |
|
||
| [ buffer.bindScreen](#bufferbindscreen-address-) |
|
||
| [ buffer.bindGPU](#bufferbindgpu-address-) |
|
||
| [Методы отрисовки](#Методы-отрисовки) |
|
||
| [ buffer.draw](#bufferdraw-force-) |
|
||
| [ buffer.setDrawLimit](#buffersetdrawlimit-x1-y1-x2-y2-) |
|
||
| [ buffer.getDrawLimit](#buffergetdrawlimit--int-x1-int-y1-int-x2-int-y2) |
|
||
| [ buffer.copy](#buffercopy-x-y-width-height--table-pixeldata) |
|
||
| [ buffer.paste](#bufferpaste-x-y-pixeldata-) |
|
||
| [ buffer.set](#bufferpaste-x-y-pixeldata-) |
|
||
| [ buffer.get](#bufferpaste-x-y-pixeldata-) |
|
||
| [ 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-) |
|
||
| [ buffer.semiPixelLine](#buffersemipixelline-x1-y1-x2-y2-color-) |
|
||
| [ buffer.semiPixelCircle](#buffersemipixelcircle-xcenter-ycenter-radius-color-) |
|
||
| [ buffer.semiPixelBezierCurve](#buffersemipixelbeziercurve-points-color-precision-) |
|
||
| [Вспомогательные методы:](#Вспомогательные-методы) |
|
||
| [ buffer.flush](#bufferflush-width-height-) |
|
||
| [ buffer.getIndexByCoordinates](#buffergetindexbycoordinates-x-y--int-index) |
|
||
| [ buffer.getCoordinatesByIndex](#buffergetcoordinatesbyindex-index--int-x-int-y) |
|
||
| [ buffer.rawSet](#bufferrawset-index-background-foreground-symbol-) |
|
||
| [ buffer.rawGet](#bufferrawget-index--int-background-int-foreground-char-symbol) |
|
||
| [Практический пример #1](#Практический-пример-1) |
|
||
|
||
|
||
О библиотеке
|
||
======
|
||
DoubleBuffering - низкоуровневая библиотека для эффективного использования ресурсов GPU и отрисовки содержимого экрана с предельно возможной скоростью. К примеру, с ее помощью реализован наш игровой движок с динамическим освещением сцен, а также небольшая игра на алгоритме рейкастинга, выдающие более чем достойные значения FPS:
|
||
|
||

|
||
|
||

|
||
|
||
Сама суть библиотеки очень проста: в оперативной памяти хранится два массива, содержащих информацию о пикселях на экране. Первый хранит то, что отображено в данный момент, а второй - то, что пользователь желает отрисовать. После осуществления всех операций отрисовки пользователь вызывает метод buffer.**draw**(), затем система автоматически определяет изменившиеся пиксели, группирует их в промежуточный буфер, чтобы число GPU-операций было минимальным, а затем выводит изменения на экран.
|
||
|
||
По сравнению с стандартной отрисовкой время отображения сокращается в сотни и тысячи раз. На рисунке ниже наглядно показана эффективность библиотеки:
|
||
|
||

|
||
|
||
Цена таких космических скоростей - повышенный расход оперативной памяти. Чтобы предельно уменьшить его, мы используем одномерную структуру экранных массивов вместо трехмерной:
|
||
|
||

|
||
|
||
Для получения данных о пикселях используются специальные методы, преобразующие экранные координаты в индексы экранного буфера и наоборот, подробнее об этом написано ниже в разделе "**Вспомогательные методы**".
|
||
|
||
Кроме того, библиотека не обращается ни к одной lua-таблице напрямую, заменяя их на переменные-аналоги и избегая при этом расчетов данных хеш-таблиц: к примеру, каждый метод GPU экранирован, и вместо gpu.setBackground используется GPUSetBackground(). При грамотной реализации такой подход колоссально увеличивает производительность, не нагружая при этом Lua GC.
|
||
|
||
Установка
|
||
======
|
||
|
||
| Библиотека | Функционал |
|
||
| ------ | ------ |
|
||
| *[advancedLua](https://github.com/IgorTimofeev/OpenComputers/blob/master/lib/advancedLua.lua)* | Дополнение стандартных библиотек Lua множеством функций: быстрой сериализацией таблиц, переносом строк, методами обработки бинарных данных и т.д. |
|
||
| *[color](https://github.com/IgorTimofeev/OpenComputers/blob/master/lib/color.lua)* | Экструзия цветовых каналов, альфа-блендинг, поддержка различных палитр и конвертации цвета в 8-битный формат |
|
||
| *[image](https://github.com/IgorTimofeev/OpenComputers/blob/master/lib/image.lua)* | Реализация стандарта изображений для OpenComputers и базовые методы их обработки: транспонирование, обрезка, поворот, отражение и т.д. |
|
||
| *[OCIF](https://github.com/IgorTimofeev/OpenComputers/blob/master/lib/FormatModules/OCIF.lua)* | Модуль формата изображения OCIF (OpenComputers Image Format) для библиотеки image, написанный с учетом особенностей мода и реализующий эффективное сжатие пиксельных данных |
|
||
| *[doubleBuffering](https://github.com/IgorTimofeev/OpenComputers/blob/master/lib/doubleBuffering.lua)* | Данная библиотека |
|
||
|
||
Вы можете использовать имеющиеся выше ссылки для установки зависимостей вручную или запустить автоматический [установщик](https://pastebin.com/vTM8nbSZ), загружающий все необходимые файлы за вас:
|
||
|
||
pastebin run vTM8nbSZ
|
||
|
||
Основные методы
|
||
======
|
||
|
||
buffer.**getResolution**(): *int* width, *int* height
|
||
-----------------------------------------------------------
|
||
Получить разрешение экранного буфера. Для удобства также имеются методы buffer.**getWidth**() и buffer.**getHeight**().
|
||
|
||
buffer.**setResolution**( width, height )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | width | Ширина буфера |
|
||
| *int* | height | Высота буфера |
|
||
|
||
Установить разрешение экранного буфера и GPU равным указанному. Содержимое буфера при этом будет заполнено черными пикселями с символом пробела.
|
||
|
||
buffer.**bindScreen**( address )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *string* | address | Адрес компонента экрана |
|
||
|
||
Связать используемую буфером видеокарту с указанным адресом компонента экрана. Содержимое буфера при этом будет очищено черными пикселями с символом пробела.
|
||
|
||
buffer.**bindGPU**( address )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *string* | address | Адрес компонента видеокарты |
|
||
|
||
Изменить используемую буфером видеокарту на указанную. Содержимое буфера при этом будет очищено черными пикселями с символом пробела.
|
||
|
||
buffer.**getGPUProxy**( ): *table* GPUProxy
|
||
-----------------------------------------------------------
|
||
Получить указатель на proxy используемого буфером компонента видеокарты.
|
||
|
||
Методы отрисовки
|
||
======
|
||
|
||
buffer.**draw**( [force] )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| [*boolean* | force] | Принудительная отрисовка |
|
||
|
||
Отрисовать содержимое буфера на экран. Если имеется опциональный аргумент *force*, то содержимое буфера будет отрисовано полностью и вне зависимости от изменившихся пикселей.
|
||
|
||
buffer.**setDrawLimit**( x1, y1, x2, y2 )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x1 | Координата первой точки лимита отрисовки по оси x |
|
||
| *int* | y1 | Координата первой точки лимита отрисовки по оси y |
|
||
| *int* | x2 | Координата второй точки лимита отрисовки по оси x |
|
||
| *int* | y2 | Координата второй точки лимита отрисовки по оси y |
|
||
|
||
Установить лимит отрисовки буфера до указанного. При этом любые операции, выходящие за границы лимита, будут игнорироваться. По умолчанию буфер всегда имеет лимит отрисовки в диапазонах **x ∈ [1; buffer.width]** и **y ∈ [1; buffer.height]**
|
||
|
||
buffer.**getDrawLimit**( ): *int* x1, *int* y1, *int* x2, *int* y2
|
||
-----------------------------------------------------------
|
||
Получить текущий лимит отрисовки.
|
||
|
||
buffer.**copy**( x, y, width, height ): *table* pixelData
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата копируемой области по оси x |
|
||
| *int* | y | Координата копируемой области по оси y |
|
||
| *int* | width | Ширина копируемой области |
|
||
| *int* | height | Высота копируемой области |
|
||
|
||
Скопировать содержимое указанной области из буфера и выдать в виде таблицы. Впоследствии можно использовать с buffer.**paste**(...).
|
||
|
||
buffer.**paste**( x, y, pixelData )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата вставки по оси x |
|
||
| *int* | y | Координата вставки по оси y |
|
||
| *table* | pixelData | Таблица со скопированной ранее областью буфера |
|
||
|
||
Вставить скопированное содержимое буфера по указанным координатам.
|
||
|
||
buffer.**set**( x, y, background, foreground, symbol )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата по оси x |
|
||
| *int* | y | Координата по оси y |
|
||
| *int* | background | Цвет фона |
|
||
| *int* | foreground | Цвет символа |
|
||
| *char* | symbol | Символ |
|
||
|
||
Установить значение конкретного пикселя на экране. Полезно для мелкого и точного редактирования.
|
||
|
||
buffer.**get**( x, y ): *int* background, *int* foreground, *char* symbol
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата по оси x |
|
||
| *int* | y | Координата по оси y |
|
||
|
||
Получить значение конкретного пикселя на экране.
|
||
|
||
buffer.**square**( x, y, width, height, background, foreground, symbol, transparency )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата прямоугольника по оси x |
|
||
| *int* | y | Координата прямоугольника по оси y |
|
||
| *int* | width | Ширина прямоугольника |
|
||
| *int* | height | Высота прямоугольника |
|
||
| *int* | background | Цвет фона прямоугольника |
|
||
| *int* | foreground | Цвет символов прямоугольника |
|
||
| *char* | symbol | Символ, которым будет заполнен прямоугольник |
|
||
| [*float* | transparency] | Опциональная прозрачность прямоугольника |
|
||
|
||
Заполнить прямоугольную область указанными данными. При указании прозрачности в диапазоне [0.0; 1.0] прямоугольник будет накладываться поверх существующей информации, словно прозрачное стеклышко.
|
||
|
||
buffer.**clear**( [color, transparency] )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| [*int* | background] | Опциональный цвет фона |
|
||
| [*float* | transparency] | Опциональная прозрачность фона |
|
||
|
||
Работает как buffer.**square**(...), однако применяется сразу ко всем пикселям буфера. Если аргументов не передается, то буфер заполняется стандартным черным цветом и символом пробела. Удобно для быстрой очистки содержимого буфера.
|
||
|
||
buffer.**text**( x, y, color, text, transparency )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата текста по оси x |
|
||
| *int* | y | Координата текста по оси y |
|
||
| *int* | foreground | Цвет текста |
|
||
| *string* | text | Текст |
|
||
| [*float* | transparency] | Опциональная прозрачность текста |
|
||
|
||
Нарисовать текст указанного цвета поверх имеющихся пикселей. Цвет фона при этом остается прежним. Можно также указать опциональную прозрачность текста текста в диапазоне [0.0; 1.0].
|
||
|
||
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 )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата изображения по оси x |
|
||
| *int* | y | Координата изображения по оси y |
|
||
| *table* | picture | Загруженное изображение |
|
||
|
||
Нарисовать загруженное через image.**load**(*string* path) изображение. Альфа-канал изображения также поддерживается.
|
||
|
||
Методы полупиксельной отрисовки
|
||
======
|
||
|
||
Все методы полупиксельной отрисовки позволяют избежать эффекта удвоения высоты пикселя консольной графики, используя специальные символы наподобие "▄". При этом передаваемые координаты по оси **Y** должны принадлежать промежутку **[0; buffer.height * 2]**.
|
||
|
||
|
||
buffer.**semiPixelSet**( x, y, color )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x1 | Координата пикселя по оси x |
|
||
| *int* | y1 | Координата пикселя по оси y |
|
||
| *int* | color | Цвет пикселя |
|
||
|
||
Установка пиксельного значения в указанной точке.
|
||
|
||
buffer.**semiPixelSquare**( x, y, width, height, color )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата прямоугольника по оси x |
|
||
| *int* | y | Координата прямоугольника по оси y |
|
||
| *int* | width | Ширина прямоугольника |
|
||
| *int* | height | Высота прямоугольника |
|
||
| *int* | color | Цвет прямоугольника |
|
||
|
||
Отрисовка прямоугольника с указанными параметрами.
|
||
|
||
buffer.**semiPixelLine**( x1, y1, x2, y2, color )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x1 | Координата первой точки линии по оси x |
|
||
| *int* | y1 | Координата первой точки линии по оси y |
|
||
| *int* | x2 | Координата второй точки линии по оси x |
|
||
| *int* | y2 | Координата второй точки линии по оси y |
|
||
| *int* | color | Цвет линии |
|
||
|
||
Растеризация отрезка указанного цвета
|
||
|
||
buffer.**semiPixelCircle**( xCenter, yCenter, radius, color )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | xCenter | Координата центральной точки окружности по оси x |
|
||
| *int* | yCenter | Координата центральной точки окружности по оси y |
|
||
| *int* | radius | Радиус окружности |
|
||
| *int* | color | Цвет окружности |
|
||
|
||
buffer.**semiPixelBezierCurve**( points, color, precision )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *table* | points | Таблица вида ```{{x = 32, y = 2}, {x = 2, y = 2}, {x = 2, y = 98}}```, содержащая опорные точки для отрисовки кривой Безье |
|
||
| *int* | color | Цвет кривой Безье |
|
||
| *float* | precision | Точность отрисовки кривой Безье. Чем меньше - тем точнее |
|
||
|
||
Растеризация [кривой Безье](https://ru.wikipedia.org/wiki/%D0%9A%D1%80%D0%B8%D0%B2%D0%B0%D1%8F_%D0%91%D0%B5%D0%B7%D1%8C%D0%B5) с указанным цветом.
|
||
|
||
Вспомогательные методы
|
||
======
|
||
|
||
Ниже перечислены методы, используемые самой библиотекой или приложениями, требующими максимального быстродействия и рассчитывающими пиксельные данные буфера вручную. В большинстве случаев они не пригождаются, однако для ознакомления указаны.
|
||
|
||
buffer.**flush**( [width, height] )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | width | Ширина буфера |
|
||
| *int* | height | Высота буфера |
|
||
|
||
Метод, устанавливающий разрешение экранного буфера равным указанному и заполняющий его черными пикселями с символом пробела. В отличие от buffer.**setResolution** не изменяет текущего разрешения GPU. Если опциональные аргументы не указаны, то размер буфера становится эквивалентным текущему разрешению GPU.
|
||
|
||
buffer.**getIndex*( x, y ): int index
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | x | Координата пикселя экрана по оси x |
|
||
| *int* | y | Координата пикселя экрана по оси y |
|
||
|
||
Метод, преобразующий экранные координаты в индекс экраннного буфера. К примеру, пиксель 2x1 имеет индекс буфера 4, а пиксель 3x1 имеет индекс буфера 7.
|
||
|
||
buffer.**getCoordinates**( index ): int x, int y
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | index | Индекс экранного буфера |
|
||
|
||
Метод, преобразующий индекс буфера в соответствующие ему координаты на экране.
|
||
|
||
buffer.**rawSet**( index, background, foreground, symbol )
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | index | Индекс экранного буфера |
|
||
| *int* | background | Цвет фона |
|
||
| *int* | foreground | Цвет символа |
|
||
| *char* | symbol | Символ |
|
||
|
||
Метод, устанавливающий соответствующие значения цветов и символа пикселю с указанным индексом.
|
||
|
||
buffer.**rawGet**( index ): int background, int foreground, char symbol
|
||
-----------------------------------------------------------
|
||
| Тип | Аргумент | Описание |
|
||
| ------ | ------ | ------ |
|
||
| *int* | index | Индекс экранного буфера |
|
||
|
||
Метод, возвращающий соответствующие значения цветов и символа пикселя с указанным индексом.
|
||
|
||
Практический пример
|
||
======
|
||
|
||
```lua
|
||
-- Подключаем библиотеки
|
||
local buffer = require("doubleBuffering")
|
||
local image = require("image")
|
||
|
||
-----------------------------------------------------------------------------------------------
|
||
|
||
-- Загружаем и рисуем изображение
|
||
buffer.image(1, 1, image.load("/MineOS/Pictures/Raspberry.pic"))
|
||
-- Заполняем буфер черным цветом с прозрачностью 0.6, чтобы изображение было чуть темнее
|
||
buffer.clear(0x0, 0.6)
|
||
|
||
-- Рисуем 10 квадратиков, заполненных случайным цветом
|
||
local x, y, xStep, yStep = 2, 2, 4, 2
|
||
for i = 1, 10 do
|
||
buffer.square(x, y, 6, 3, math.random(0x0, 0xFFFFFF), 0x0, " ")
|
||
x, y = x + xStep, y + yStep
|
||
end
|
||
|
||
-- Рисуем желтую окружность
|
||
buffer.semiPixelCircle(22, 22, 10, 0xFFDB40)
|
||
-- Рисуем белую линию
|
||
buffer.semiPixelLine(2, 36, 35, 3, 0xFFFFFF)
|
||
-- Рисуем зеленую кривую Безье с точностью 0.01
|
||
buffer.semiPixelBezierCurve(
|
||
{
|
||
{ x = 2, y = 63},
|
||
{ x = 63, y = 63},
|
||
{ x = 63, y = 2}
|
||
},
|
||
0x44FF44,
|
||
0.01
|
||
)
|
||
|
||
-- Выводим содержимое буфера на экран
|
||
buffer.draw()
|
||
```
|
||
|
||
Результат:
|
||
|
||

|