Redo transparency ordering
This commit is contained in:
parent
071b00d922
commit
ace6a3cea9
37
zchunk.lua
37
zchunk.lua
@ -4,7 +4,7 @@ local zprite = require("zprite.zprite")
|
|||||||
---@field private _chunks {integer: {z: zprite, x: integer, y: integer}}
|
---@field private _chunks {integer: {z: zprite, x: integer, y: integer}}
|
||||||
---@field private _chunk_size integer
|
---@field private _chunk_size integer
|
||||||
---@field private _chunk_height integer
|
---@field private _chunk_height integer
|
||||||
---@field private _chunk_wrap integer
|
---@field private _chunk_wrap integer?
|
||||||
---@field private _texture love.Image
|
---@field private _texture love.Image
|
||||||
---@field private _height_scale number
|
---@field private _height_scale number
|
||||||
local zchunk = {}
|
local zchunk = {}
|
||||||
@ -96,7 +96,7 @@ function zchunk:put(x, y, quad, layer_count, color_map, base_layer)
|
|||||||
local index = self:_chunk_index(x, y)
|
local index = self:_chunk_index(x, y)
|
||||||
if not self._chunks[index] then
|
if not self._chunks[index] then
|
||||||
self._chunks[index] = {
|
self._chunks[index] = {
|
||||||
z = zprite.new(self._texture, self._chunk_size * self._chunk_size * self._chunk_height),
|
z = zprite.new(self._texture, self._chunk_size * self._chunk_size),
|
||||||
}
|
}
|
||||||
self._chunks[index].z._height_scale = self._height_scale
|
self._chunks[index].z._height_scale = self._height_scale
|
||||||
end
|
end
|
||||||
@ -105,34 +105,19 @@ function zchunk:put(x, y, quad, layer_count, color_map, base_layer)
|
|||||||
self._chunks[index].y = math.floor(y / self._chunk_size)
|
self._chunks[index].y = math.floor(y / self._chunk_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
local transform = love.math.newTransform()
|
|
||||||
local function sort_fn(a, b)
|
|
||||||
local _, ay_rotated = transform:transformPoint(a.x, a.y)
|
|
||||||
local _, by_rotated = transform:transformPoint(b.x, b.y)
|
|
||||||
|
|
||||||
return ay_rotated < by_rotated
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Draw to the screen / current canvas
|
--- Draw to the screen / current canvas
|
||||||
---@overload fun(self, x: number, y: number, r: number?, sx: number?, sy: number?, ox: number?, oy: number?, kx: number?, ky: number?)
|
---@overload fun(self, x: number, y: number, r: number?, sx: number?, sy: number?, ox: number?, oy: number?, kx: number?, ky: number?)
|
||||||
---@overload fun(self, transform: love.Transform)
|
---@overload fun(self, transform: love.Transform)
|
||||||
function zchunk:draw(x, y, r, ...)
|
function zchunk:draw(...)
|
||||||
local chunks = {}
|
zprite._set_shader(self._height_scale)
|
||||||
for _, chunk in pairs(self._chunks) do
|
|
||||||
table.insert(chunks, chunk)
|
|
||||||
end
|
|
||||||
|
|
||||||
transform:reset()
|
for i = 1, self._chunk_height do
|
||||||
if type(x) ~= "number" then
|
for _, chunk in pairs(self._chunks) do
|
||||||
transform:apply(x)
|
chunk.z:_upload()
|
||||||
else
|
if chunk.z._instances[i] then
|
||||||
transform:rotate(r and r or 0)
|
love.graphics.drawInstanced(chunk.z._meshes[i], #chunk.z._instances[i] / 3, ...)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
table.sort(chunks, sort_fn)
|
|
||||||
|
|
||||||
for _, chunk in ipairs(chunks) do
|
|
||||||
chunk.z:draw(x, y, r, ...)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
78
zprite.lua
78
zprite.lua
@ -1,13 +1,12 @@
|
|||||||
---@class zprite
|
---@class zprite
|
||||||
---@field private _texture love.Image
|
---@field private _texture love.Image
|
||||||
---@field private _instance_vertex_count integer
|
---@field private _instance_vertex_count integer
|
||||||
---@field private _mesh love.Mesh
|
---@field private _meshes love.Mesh[]
|
||||||
---@field private _instance_buffer love.Buffer
|
---@field private _instance_buffers love.Buffer[]
|
||||||
---@field private _instances {integer: {}[]}
|
---@field private _instances {integer: {}[]}
|
||||||
---@field private _top_layer integer
|
---@field private _top_layer integer
|
||||||
---@field private _height_scale number
|
---@field private _height_scale number
|
||||||
---@field private _changed boolean
|
---@field private _changed boolean
|
||||||
---@field private _count integer
|
|
||||||
local zprite = {}
|
local zprite = {}
|
||||||
zprite.__index = zprite
|
zprite.__index = zprite
|
||||||
|
|
||||||
@ -74,44 +73,26 @@ function zprite.new(texture, max_instances)
|
|||||||
error("max_instances must be at least 1")
|
error("max_instances must be at least 1")
|
||||||
end
|
end
|
||||||
|
|
||||||
local tw, th = texture:getPixelDimensions()
|
|
||||||
local vertices = {
|
|
||||||
{ 0, 0, 0, 0 },
|
|
||||||
{ 1, 0, 1 / tw, 0 },
|
|
||||||
{ 0, 1, 0, 1 / th },
|
|
||||||
{ 1, 1, 1 / tw, 1 / th },
|
|
||||||
}
|
|
||||||
|
|
||||||
local obj = setmetatable({}, zprite)
|
local obj = setmetatable({}, zprite)
|
||||||
|
|
||||||
obj._texture = texture
|
obj._texture = texture
|
||||||
obj._instance_vertex_count = max_instances or 16384
|
obj._instance_vertex_count = max_instances or 1024
|
||||||
obj._mesh = love.graphics.newMesh({
|
obj._meshes = {}
|
||||||
{ name = "VertexPosition", format = "floatvec2", location = 0 },
|
|
||||||
{ name = "VertexTexCoord", format = "floatvec2", location = 1 },
|
|
||||||
}, vertices, "strip", "static")
|
|
||||||
obj._mesh:setTexture(texture)
|
|
||||||
obj._instance_buffer = love.graphics.newBuffer({
|
|
||||||
{ name = "InstanceData", format = "uint32vec3", location = 3 },
|
|
||||||
}, obj._instance_vertex_count, { vertex = true })
|
|
||||||
obj._instances = {}
|
obj._instances = {}
|
||||||
|
obj._instance_buffers = {}
|
||||||
obj._height_scale = 4
|
obj._height_scale = 4
|
||||||
obj._changed = false
|
obj._changed = false
|
||||||
|
|
||||||
obj._mesh:attachAttribute(3, obj._instance_buffer, "perinstance")
|
|
||||||
|
|
||||||
obj._top_layer = 0
|
obj._top_layer = 0
|
||||||
obj._count = 0
|
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Clear all drawn objects
|
--- Clear all drawn objects
|
||||||
function zprite:clear()
|
function zprite:clear()
|
||||||
-- no need to set _changed to true, as #self._instances will be 0
|
self._changed = true
|
||||||
self._instances = {}
|
self._instances = {}
|
||||||
self._top_layer = 0
|
self._top_layer = 0
|
||||||
self._count = 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add an 'entity' to be rendered
|
--- Add an 'entity' to be rendered
|
||||||
@ -183,8 +164,9 @@ function zprite:put(x, y, quad, layer_count, color_map, base_layer)
|
|||||||
|
|
||||||
local uv_scale = bit.bor(uv, scale)
|
local uv_scale = bit.bor(uv, scale)
|
||||||
|
|
||||||
table.insert(self._instances[i], { pos, uv_scale, layer_rgb })
|
table.insert(self._instances[i], pos)
|
||||||
self._count = self._count + 1
|
table.insert(self._instances[i], uv_scale)
|
||||||
|
table.insert(self._instances[i], layer_rgb)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -192,21 +174,49 @@ end
|
|||||||
---@overload fun(self, x: number, y: number, r: number?, sx: number?, sy: number?, ox: number?, oy: number?, kx: number?, ky: number?)
|
---@overload fun(self, x: number, y: number, r: number?, sx: number?, sy: number?, ox: number?, oy: number?, kx: number?, ky: number?)
|
||||||
---@overload fun(self, transform: love.Transform)
|
---@overload fun(self, transform: love.Transform)
|
||||||
function zprite:draw(...)
|
function zprite:draw(...)
|
||||||
love.graphics.setShader(ZPRITE_SHADER)
|
zprite._set_shader(self._height_scale)
|
||||||
ZPRITE_SHADER:send("HeightScale", self._height_scale)
|
|
||||||
|
|
||||||
|
self:_upload()
|
||||||
|
|
||||||
|
for i = 1, self._top_layer do
|
||||||
|
if self._instances[i] then
|
||||||
|
love.graphics.drawInstanced(self._meshes[i], #self._instances[i] / 3, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function zprite._set_shader(height_scale)
|
||||||
|
love.graphics.setShader(ZPRITE_SHADER)
|
||||||
|
ZPRITE_SHADER:send("HeightScale", height_scale)
|
||||||
|
end
|
||||||
|
|
||||||
|
function zprite:_upload()
|
||||||
if self._changed then
|
if self._changed then
|
||||||
local current = 1
|
|
||||||
for i = 1, self._top_layer do
|
for i = 1, self._top_layer do
|
||||||
if self._instances[i] then
|
if self._instances[i] then
|
||||||
self._instance_buffer:setArrayData(self._instances[i], 1, current, #self._instances[i])
|
if not self._instance_buffers[i] then
|
||||||
current = current + #self._instances[i]
|
local tw, th = self._texture:getPixelDimensions()
|
||||||
|
local vertices = {
|
||||||
|
{ 0, 0, 0, 0 },
|
||||||
|
{ 1, 0, 1 / tw, 0 },
|
||||||
|
{ 0, 1, 0, 1 / th },
|
||||||
|
{ 1, 1, 1 / tw, 1 / th },
|
||||||
|
}
|
||||||
|
self._meshes[i] = love.graphics.newMesh({
|
||||||
|
{ name = "VertexPosition", format = "floatvec2", location = 0 },
|
||||||
|
{ name = "VertexTexCoord", format = "floatvec2", location = 1 },
|
||||||
|
}, vertices, "strip", "static")
|
||||||
|
self._meshes[i]:setTexture(self._texture)
|
||||||
|
self._instance_buffers[i] = love.graphics.newBuffer({
|
||||||
|
{ name = "InstanceData", format = "uint32vec3", location = 3 },
|
||||||
|
}, self._instance_vertex_count, { vertex = true })
|
||||||
|
self._meshes[i]:attachAttribute(3, self._instance_buffers[i], "perinstance")
|
||||||
|
end
|
||||||
|
self._instance_buffers[i]:setArrayData(self._instances[i], 1, 1, #self._instances[i] / 3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self._changed = false
|
self._changed = false
|
||||||
end
|
end
|
||||||
|
|
||||||
love.graphics.drawInstanced(self._mesh, self._count, ...)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return zprite
|
return zprite
|
||||||
|
Loading…
x
Reference in New Issue
Block a user