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 _chunk_size integer
|
||||
---@field private _chunk_height integer
|
||||
---@field private _chunk_wrap integer
|
||||
---@field private _chunk_wrap integer?
|
||||
---@field private _texture love.Image
|
||||
---@field private _height_scale number
|
||||
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)
|
||||
if not self._chunks[index] then
|
||||
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
|
||||
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)
|
||||
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
|
||||
---@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)
|
||||
function zchunk:draw(x, y, r, ...)
|
||||
local chunks = {}
|
||||
for _, chunk in pairs(self._chunks) do
|
||||
table.insert(chunks, chunk)
|
||||
end
|
||||
function zchunk:draw(...)
|
||||
zprite._set_shader(self._height_scale)
|
||||
|
||||
transform:reset()
|
||||
if type(x) ~= "number" then
|
||||
transform:apply(x)
|
||||
else
|
||||
transform:rotate(r and r or 0)
|
||||
end
|
||||
|
||||
table.sort(chunks, sort_fn)
|
||||
|
||||
for _, chunk in ipairs(chunks) do
|
||||
chunk.z:draw(x, y, r, ...)
|
||||
for i = 1, self._chunk_height do
|
||||
for _, chunk in pairs(self._chunks) do
|
||||
chunk.z:_upload()
|
||||
if chunk.z._instances[i] then
|
||||
love.graphics.drawInstanced(chunk.z._meshes[i], #chunk.z._instances[i] / 3, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
78
zprite.lua
78
zprite.lua
@ -1,13 +1,12 @@
|
||||
---@class zprite
|
||||
---@field private _texture love.Image
|
||||
---@field private _instance_vertex_count integer
|
||||
---@field private _mesh love.Mesh
|
||||
---@field private _instance_buffer love.Buffer
|
||||
---@field private _meshes love.Mesh[]
|
||||
---@field private _instance_buffers love.Buffer[]
|
||||
---@field private _instances {integer: {}[]}
|
||||
---@field private _top_layer integer
|
||||
---@field private _height_scale number
|
||||
---@field private _changed boolean
|
||||
---@field private _count integer
|
||||
local zprite = {}
|
||||
zprite.__index = zprite
|
||||
|
||||
@ -74,44 +73,26 @@ function zprite.new(texture, max_instances)
|
||||
error("max_instances must be at least 1")
|
||||
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)
|
||||
|
||||
obj._texture = texture
|
||||
obj._instance_vertex_count = max_instances or 16384
|
||||
obj._mesh = love.graphics.newMesh({
|
||||
{ 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._instance_vertex_count = max_instances or 1024
|
||||
obj._meshes = {}
|
||||
obj._instances = {}
|
||||
obj._instance_buffers = {}
|
||||
obj._height_scale = 4
|
||||
obj._changed = false
|
||||
|
||||
obj._mesh:attachAttribute(3, obj._instance_buffer, "perinstance")
|
||||
|
||||
obj._top_layer = 0
|
||||
obj._count = 0
|
||||
|
||||
return obj
|
||||
end
|
||||
|
||||
--- Clear all drawn objects
|
||||
function zprite:clear()
|
||||
-- no need to set _changed to true, as #self._instances will be 0
|
||||
self._changed = true
|
||||
self._instances = {}
|
||||
self._top_layer = 0
|
||||
self._count = 0
|
||||
end
|
||||
|
||||
--- 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)
|
||||
|
||||
table.insert(self._instances[i], { pos, uv_scale, layer_rgb })
|
||||
self._count = self._count + 1
|
||||
table.insert(self._instances[i], pos)
|
||||
table.insert(self._instances[i], uv_scale)
|
||||
table.insert(self._instances[i], layer_rgb)
|
||||
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, transform: love.Transform)
|
||||
function zprite:draw(...)
|
||||
love.graphics.setShader(ZPRITE_SHADER)
|
||||
ZPRITE_SHADER:send("HeightScale", self._height_scale)
|
||||
zprite._set_shader(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
|
||||
local current = 1
|
||||
for i = 1, self._top_layer do
|
||||
if self._instances[i] then
|
||||
self._instance_buffer:setArrayData(self._instances[i], 1, current, #self._instances[i])
|
||||
current = current + #self._instances[i]
|
||||
if not self._instance_buffers[i] then
|
||||
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
|
||||
self._changed = false
|
||||
end
|
||||
|
||||
love.graphics.drawInstanced(self._mesh, self._count, ...)
|
||||
end
|
||||
|
||||
return zprite
|
||||
|
Loading…
x
Reference in New Issue
Block a user