Reduce VRAM usage by a lot
This commit is contained in:
parent
1b6c73f117
commit
9e6265d5bb
20
main.lua
20
main.lua
@ -21,30 +21,32 @@ end
|
||||
|
||||
local BIG_BLOCK = love.graphics.newQuad(24 * 9, 24 * 9, 24, 24, tex)
|
||||
|
||||
local z = require("zprite").zchunk.new(tex, 384, 40)
|
||||
z._height_scale = 10
|
||||
local z = require("zprite").zchunk.new(tex, 384, 32)
|
||||
z._height_scale = 8
|
||||
|
||||
local function update_map()
|
||||
for i = -32, 32 do
|
||||
for j = -32, 32 do
|
||||
local layers = love.math.simplexNoise(i * 0.02, j * 0.02) * 34 + 6
|
||||
z:clear()
|
||||
for i = -64, 64 do
|
||||
for j = -64, 64 do
|
||||
local layers = love.math.simplexNoise(i * 0.02, j * 0.02) * 29 + 3
|
||||
z:put(i * 24, j * 24, BIG_BLOCK, math.floor(layers) + 1, layers < 23 and dirt_color or mountain_color)
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local co = coroutine.create(update_map)
|
||||
|
||||
local angle = 0
|
||||
|
||||
function love.update(dt)
|
||||
if coroutine.status(co) == "suspended" then
|
||||
coroutine.resume(co)
|
||||
for _ = 1, 4 do
|
||||
if coroutine.status(co) == "suspended" then
|
||||
coroutine.resume(co)
|
||||
end
|
||||
end
|
||||
angle = math.fmod(angle + dt * 0.8, 2 * math.pi)
|
||||
end
|
||||
|
||||
function love.draw()
|
||||
z:draw(love.graphics.getWidth() / 2, love.graphics.getHeight() / 2 + 128, angle, 0.3, 0.3)
|
||||
z:draw(love.graphics.getWidth() / 2, love.graphics.getHeight() / 2 + 128, angle, 0.2, 0.2)
|
||||
end
|
||||
|
@ -45,24 +45,34 @@ function zchunk:_chunk_index(x, y)
|
||||
return math.floor(x / self._chunk_size) + math.floor(y / self._chunk_size) * 1e7
|
||||
end
|
||||
|
||||
---@param x integer
|
||||
---@param y integer
|
||||
---@param x integer?
|
||||
---@param y integer?
|
||||
function zchunk:remove(x, y)
|
||||
local index = self:_chunk_index(x, y)
|
||||
if not self._chunks[index] then
|
||||
return
|
||||
if not x then
|
||||
self._chunks = {}
|
||||
else
|
||||
local index = self:_chunk_index(x, y)
|
||||
if not self._chunks[index] then
|
||||
return
|
||||
end
|
||||
self._chunks[index] = {}
|
||||
end
|
||||
self._chunks[index] = {}
|
||||
end
|
||||
|
||||
---@param x integer
|
||||
---@param y integer
|
||||
---@param x integer?
|
||||
---@param y integer?
|
||||
function zchunk:clear(x, y)
|
||||
local index = self:_chunk_index(x, y)
|
||||
if not self._chunks[index] then
|
||||
return
|
||||
if not x then
|
||||
for _, chunk in pairs(self._chunks) do
|
||||
chunk.z:clear()
|
||||
end
|
||||
else
|
||||
local index = self:_chunk_index(x, y)
|
||||
if not self._chunks[index] then
|
||||
return
|
||||
end
|
||||
self._chunks[index].z:clear()
|
||||
end
|
||||
self._chunks[index].z:clear()
|
||||
end
|
||||
|
||||
--- Add an 'entity' to be rendered
|
||||
|
@ -12,26 +12,42 @@ local zprite = {}
|
||||
zprite.__index = zprite
|
||||
|
||||
local ZPRITE_SHADER = love.graphics.newShader([[
|
||||
#pragma language glsl4
|
||||
|
||||
varying vec4 VsColorOut;
|
||||
|
||||
#ifdef VERTEX
|
||||
layout (location = 3) attribute vec2 InstancePosition;
|
||||
layout (location = 4) attribute vec2 InstanceTextureOffset;
|
||||
layout (location = 5) attribute vec2 InstanceScale;
|
||||
layout (location = 6) attribute float InstanceLayer;
|
||||
layout (location = 7) attribute vec4 InstanceColor;
|
||||
layout (location = 3) attribute uvec3 InstanceData;
|
||||
|
||||
uniform float HeightScale;
|
||||
|
||||
vec4 position(mat4 transform_projection, vec4 vertex_position)
|
||||
{
|
||||
vertex_position.xy *= InstanceScale;
|
||||
vertex_position.xy += InstancePosition.xy;
|
||||
vertex_position.z = InstanceLayer / 1024;
|
||||
VaryingTexCoord.xy *= InstanceScale;
|
||||
VaryingTexCoord.xy += InstanceTextureOffset;
|
||||
VsColorOut = InstanceColor;
|
||||
return (transform_projection * vertex_position) + vec4(0, (InstanceLayer * HeightScale) / love_ScreenSize.y, 0, 0);
|
||||
uint position_x = bitfieldExtract(InstanceData.x, 0, 16);
|
||||
uint position_y = bitfieldExtract(InstanceData.x, 16, 16);
|
||||
vec2 position = vec2(position_x, position_y) - vec2(32768, 32768);
|
||||
|
||||
uint uv_x = bitfieldExtract(InstanceData.y, 0, 10);
|
||||
uint uv_y = bitfieldExtract(InstanceData.y, 10, 10);
|
||||
vec2 uv = vec2(uv_x, uv_y) / vec2(1024, 1024);
|
||||
|
||||
uint scale_x = bitfieldExtract(InstanceData.y, 20, 6);
|
||||
uint scale_y = bitfieldExtract(InstanceData.y, 26, 6);
|
||||
vec2 scale = vec2(scale_x, scale_y);
|
||||
|
||||
uint layer = bitfieldExtract(InstanceData.z, 0, 8);
|
||||
|
||||
uint r = bitfieldExtract(InstanceData.z, 8, 8);
|
||||
uint g = bitfieldExtract(InstanceData.z, 16, 8);
|
||||
uint b = bitfieldExtract(InstanceData.z, 24, 8);
|
||||
vec3 color = vec3(r, g, b) / vec3(256, 256, 256);
|
||||
|
||||
vertex_position.xy *= scale;
|
||||
vertex_position.xy += position;
|
||||
VaryingTexCoord.xy *= scale;
|
||||
VaryingTexCoord.xy += uv;
|
||||
VsColorOut = vec4(color, 1);
|
||||
return (transform_projection * vertex_position) + vec4(0, (layer * HeightScale) / love_ScreenSize.y, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -76,21 +92,13 @@ function zprite.new(texture, max_instances)
|
||||
}, vertices, "strip", "static")
|
||||
obj._mesh:setTexture(texture)
|
||||
obj._instance_buffer = love.graphics.newBuffer({
|
||||
{ name = "InstancePosition", format = "floatvec2", location = 3 },
|
||||
{ name = "InstanceTextureOffset", format = "floatvec2", location = 4 },
|
||||
{ name = "InstanceScale", format = "floatvec2", location = 5 },
|
||||
{ name = "InstanceLayer", format = "float", location = 6 },
|
||||
{ name = "InstanceColor", format = "floatvec4", location = 7 },
|
||||
{ name = "InstanceData", format = "uint32vec3", location = 3 },
|
||||
}, obj._instance_vertex_count, { vertex = true })
|
||||
obj._instances = {}
|
||||
obj._height_scale = 4
|
||||
obj._changed = false
|
||||
|
||||
obj._mesh:attachAttribute(3, obj._instance_buffer, "perinstance")
|
||||
obj._mesh:attachAttribute(4, obj._instance_buffer, "perinstance")
|
||||
obj._mesh:attachAttribute(5, obj._instance_buffer, "perinstance")
|
||||
obj._mesh:attachAttribute(6, obj._instance_buffer, "perinstance")
|
||||
obj._mesh:attachAttribute(7, obj._instance_buffer, "perinstance")
|
||||
|
||||
obj._top_layer = 0
|
||||
obj._count = 0
|
||||
@ -123,21 +131,49 @@ function zprite:put(x, y, quad, layer_count, color_map, base_layer)
|
||||
|
||||
self._changed = true
|
||||
|
||||
local pos_x = bit.band(x + 32768, 0xFFFF)
|
||||
local pos_y = bit.lshift(bit.band(y + 32768, 0xFFFF), 16)
|
||||
local pos = bit.bor(pos_x, pos_y)
|
||||
|
||||
local qx, qy, qw, qh = quad:getViewport()
|
||||
local tw, th = self._texture:getPixelDimensions()
|
||||
|
||||
local uv_x = bit.band(1024 * qx / tw, 0x3FF)
|
||||
local uv_y = bit.lshift(bit.band(1024 * qy / th, 0x3FF), 10)
|
||||
local uv = bit.bor(uv_x, uv_y)
|
||||
|
||||
local scale_x = bit.lshift(bit.band(qw, 0x3F), 20)
|
||||
local scale_y = bit.lshift(bit.band(qh, 0x3F), 26)
|
||||
local scale = bit.bor(scale_x, scale_y)
|
||||
|
||||
local uv_scale = bit.bor(uv, scale)
|
||||
|
||||
for i = 1, layer_count do
|
||||
local r, g, b, a = color_map(i)
|
||||
if not a then
|
||||
a = 1
|
||||
end
|
||||
if not self._instances[i + base_layer] then
|
||||
self._instances[i + base_layer] = {}
|
||||
if i > self._top_layer then
|
||||
self._top_layer = i
|
||||
end
|
||||
end
|
||||
table.insert(self._instances[i], { x, y, qx / tw, qy / th, qw, qh, i + base_layer, r, g, b, a })
|
||||
local layer = bit.band(i + base_layer, 0xFF)
|
||||
|
||||
local r, g, b = color_map(i)
|
||||
if r > 1 then
|
||||
r = 1
|
||||
end
|
||||
if g > 1 then
|
||||
g = 1
|
||||
end
|
||||
if b > 1 then
|
||||
b = 1
|
||||
end
|
||||
local rb = bit.lshift(bit.band(r * 0xFF, 0xFF), 8)
|
||||
local gb = bit.lshift(bit.band(g * 0xFF, 0xFF), 16)
|
||||
local bb = bit.lshift(bit.band(b * 0xFF, 0xFF), 24)
|
||||
|
||||
local layer_rgb = bit.bor(bit.bor(layer, rb), bit.bor(gb, bb))
|
||||
|
||||
table.insert(self._instances[i], { pos, uv_scale, layer_rgb })
|
||||
self._count = self._count + 1
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user