Skip to content

Commit

Permalink
attempt at adding transparent meshes
Browse files Browse the repository at this point in the history
  • Loading branch information
brennop committed Apr 16, 2023
1 parent 46c9084 commit 8ca8b7e
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 120 deletions.
7 changes: 5 additions & 2 deletions src/blocks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ blockTypes = {
{ 1, 0.75, -1 },
{ -1, -1, -1 },
{ 1, -1, -1 },
}
},
alpha = 0.5
}),
-- 5: sand
cube({ { 3, 7 }, { 3, 7 }, { 3, 7 }, { 3, 7 }, { 3, 7 }, { 3, 7 } }),
-- 6: wood
cube({ { 14, 13 }, { 15, 13 }, { 14, 13 }, { 15, 13 }, { 14, 13 }, { 14, 13 } }),
-- 7: leaves
cube({ { 1, 17 }, { 1, 17 }, { 1, 17 }, { 1, 17 }, { 1, 17 }, { 1, 17 } }, { }),
cube({ { 1, 17 }, { 1, 17 }, { 1, 17 }, { 1, 17 }, { 1, 17 }, { 1, 17 } }, {
alpha = 0.9
}),
}

return blockTypes
2 changes: 2 additions & 0 deletions src/camera.lua
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ function Camera:drawWorld()
end
end
end

self.world:draw()
end

function Camera:drawShadowMap()
Expand Down
50 changes: 40 additions & 10 deletions src/chunk.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ function Chunk:new(x, y, z, world)
self.dirty = true

self.mesh = nil
self.transparentMesh = nil

self.model = Matrix()
self.model[4] = self.position.x
self.model[8] = self.position.y
self.model[12] = self.position.z

self.channel = self:__tostring()

end

function Chunk:__tostring()
Expand All @@ -58,6 +58,9 @@ function Chunk:load(thread)
-- each vertex is currently 36 bytes
self.verticesData = love.data.newByteData(maxVertices * 36)

-- FIXME: going on an assumption that the transparent vertices will be less than the opaque ones
self.transparentVerticesData = love.data.newByteData(maxVertices * 36 * 0.5)

-- add 1 to the size to include the border
local blocks = {}
for i = 0, CHUNK_SIZE + 1 do
Expand All @@ -71,7 +74,7 @@ function Chunk:load(thread)
end
end

thread:start(self.position:table(), blocks, self.channel, blockTypes, self.verticesData)
thread:start(self.position:table(), blocks, self.channel, blockTypes, self.verticesData, self.transparentVerticesData)
end

function Chunk:getBlock(x, y, z)
Expand Down Expand Up @@ -114,18 +117,38 @@ function Chunk:setBlock(x, y, z, block)
end

function Chunk:update()
local message = love.thread.getChannel(self.channel):pop()
for _, suffix in ipairs { "opaque", "transparent" } do
local message = love.thread.getChannel(self.channel .. suffix):pop()

if message then
local mesh, data

if suffix == "opaque" then
mesh = self.mesh
data = self.verticesData
else
mesh = self.transparentMesh
data = self.transparentVerticesData
end

if message then
local numVertices = message
local numVertices = message

if self.mesh then self.mesh:release() end
if numVertices == 0 then return end

self.mesh = love.graphics.newMesh(format, numVertices, "triangles", "static")
self.mesh:setTexture(tileset)
self.mesh:setVertices(self.verticesData, 1, numVertices)
if mesh then mesh:release() end

self.verticesData:release()
mesh = love.graphics.newMesh(format, numVertices, "triangles", "static")
mesh:setTexture(tileset)
mesh:setVertices(data, 1, numVertices)

if suffix == "opaque" then
self.mesh = mesh
else
self.transparentMesh = mesh
end

data:release()
end
end
end

Expand All @@ -134,6 +157,13 @@ function Chunk:draw()
love.graphics.getShader():send("modelMatrix", self.model)
love.graphics.draw(self.mesh)
end

if self.transparentMesh then
self.world.transparentMeshes[#self.world.transparentMeshes + 1] = {
mesh = self.transparentMesh,
model = self.model
}
end
end

return Chunk
6 changes: 4 additions & 2 deletions src/cube.lua
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ return function(textures, config)
vertices[vertex][3] * 0.5,
u + uvs[uv][1] * step,
v + uvs[uv][2] * step,
normals[normal],
alpha
normals[normal]
}
end
end

cube.alpha = alpha
cube.opaque = alpha == 1

return cube
end
59 changes: 0 additions & 59 deletions src/load_mesh.lua

This file was deleted.

140 changes: 98 additions & 42 deletions src/mesh.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
local CHUNK_SIZE = 8
local CHUNK_HEIGHT = 32
-- to be run on another thread
local CHUNK_SIZE = 16
local CHUNK_HEIGHT = 48

local position, blocks, channel, blockTypes, oData, tData = ...

local ffi = require "ffi"

local shading = {
0.3, 0.4, 0.6, 1,
}

function sign(value)
local function sign(value)
if value > 0 then
return 1
elseif value < 0 then
Expand All @@ -15,53 +20,104 @@ function sign(value)
end
end

function setVertex(index, i, mesh, x, y, z, value, getBlock, outVertex)
local function getBlock(i, j, k)
return blocks[i][j][k]
end

function setVertex(index, i, mesh, x, y, z, outVertex)
local block = getBlock(x, y, z)

if (value == 0 or (value == 4 and block ~= 4)) and mesh then
local vertex = mesh[index*6+i]
local vx, vy, vz, u, v, normal, alpha = unpack(vertex)

local dx, dy, dz = sign(vx), sign(vy), sign(vz)
local nx, ny, nz = normal[1], normal[2], normal[3]
local side1, side2, corner, m

if nx ~= 0 then
side1 = getBlock(x + nx, y + dy, z) == 0 and 0 or 1
side2 = getBlock(x + nx, y, z + dz) == 0 and 0 or 1
corner = getBlock(x + nx, y + dy, z + dz) == 0 and 0 or 1
m = nx == 1 and 0.8 or 0.6
elseif ny ~= 0 then
side1 = getBlock(x + dx, y + ny, z) == 0 and 0 or 1
side2 = getBlock(x, y + ny, z + dz) == 0 and 0 or 1
corner = getBlock(x + dx, y + ny, z + dz) == 0 and 0 or 1
m = ny == 1 and 1 or 0.4
elseif nz ~= 0 then
side1 = getBlock(x + dx, y, z + nz) == 0 and 0 or 1
side2 = getBlock(x, y + dy, z + nz) == 0 and 0 or 1
corner = getBlock(x + dx, y + dy, z + nz) == 0 and 0 or 1
m = nz == 1 and 0.6 or 0.8
end
local vertex = mesh[index*6+i]
local vx, vy, vz, u, v, normal = unpack(vertex)

local state
local dx, dy, dz = sign(vx), sign(vy), sign(vz)
local nx, ny, nz = normal[1], normal[2], normal[3]
local side1, side2, corner, m

if side1 == 1 and side2 == 1 then
state = 1
else
state = 4 - side1 - side2 - corner
end
if nx ~= 0 then
side1 = getBlock(x + nx, y + dy, z) == 0 and 0 or 1
side2 = getBlock(x + nx, y, z + dz) == 0 and 0 or 1
corner = getBlock(x + nx, y + dy, z + dz) == 0 and 0 or 1
m = nx == 1 and 0.8 or 0.6
elseif ny ~= 0 then
side1 = getBlock(x + dx, y + ny, z) == 0 and 0 or 1
side2 = getBlock(x, y + ny, z + dz) == 0 and 0 or 1
corner = getBlock(x + dx, y + ny, z + dz) == 0 and 0 or 1
m = ny == 1 and 1 or 0.4
elseif nz ~= 0 then
side1 = getBlock(x + dx, y, z + nz) == 0 and 0 or 1
side2 = getBlock(x, y + dy, z + nz) == 0 and 0 or 1
corner = getBlock(x + dx, y + dy, z + nz) == 0 and 0 or 1
m = nz == 1 and 0.6 or 0.8
end

local state

if side1 == 1 and side2 == 1 then
state = 1
else
state = 4 - side1 - side2 - corner
end

s = shading[state] * 255

s = shading[state] * 255
outVertex.x, outVertex.y, outVertex.z = vx + x, vy + y, vz + z
outVertex.u, outVertex.v = u, v
outVertex.nx, outVertex.ny, outVertex.nz = nx, ny, nz
outVertex.r, outVertex.g, outVertex.b, outVertex.a = s, s, s, mesh.alpha * 255

outVertex.x, outVertex.y, outVertex.z = vx + x, vy + y, vz + z
outVertex.u, outVertex.v = u, v
outVertex.nx, outVertex.ny, outVertex.nz = nx, ny, nz
outVertex.r, outVertex.g, outVertex.b, outVertex.a = s, s, s, alpha * 255
return true
end

ffi.cdef [[
typedef struct {
float x, y, z;
float u, v;
float nx, ny, nz;
unsigned char r, g, b, a;
} ck_vertex;
]]


function getMesh(opaque, data)
local pointer = ffi.cast('ck_vertex*', data:getFFIPointer())

local vi = 0

function setFace(index, mesh, x, y, z, value)
for i = 1, 6 do
local vertex = pointer[vi]
local prev = blockTypes[value]

return true
if (value == 0 or prev.opaque ~= opaque) and mesh.opaque == opaque then
setVertex(index, i, mesh, x, y, z, vertex)
vi = vi + 1
end
end
end

for k = 1, CHUNK_SIZE do
for j = 1, CHUNK_HEIGHT do
for i = 1, CHUNK_SIZE do
local block = blocks[i][j][k]
local mesh = blockTypes[block]

if mesh then
setFace(0, mesh, i, j, k, getBlock(i, j, k + 1))
setFace(1, mesh, i, j, k, getBlock(i, j + 1, k))
setFace(2, mesh, i, j, k, getBlock(i, j, k - 1))
setFace(3, mesh, i, j, k, getBlock(i, j - 1, k))
setFace(4, mesh, i, j, k, getBlock(i + 1, j, k))
setFace(5, mesh, i, j, k, getBlock(i - 1, j, k))
end
end
end
end

return false
local channelSuffix = opaque and "opaque" or "transparent"

love.thread.getChannel(channel .. channelSuffix):supply(vi)
end

return setVertex
getMesh(true, oData)
getMesh(false, tData)
13 changes: 8 additions & 5 deletions src/world.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ function World:new()
self.threads = {}

for i = 1, 4 do
self.threads[i] = love.thread.newThread("src/load_mesh.lua")
self.threads[i] = love.thread.newThread("src/mesh.lua")
end

self:loadChunk(0, 0)

self.transparentMeshes = {}

return self
end

Expand Down Expand Up @@ -140,11 +142,12 @@ function World:update(dt)
end

function World:draw()
for i, v in pairs(self.chunks) do
for j, chunk in pairs(v) do
chunk:draw()
end
for i, data in pairs(self.transparentMeshes) do
love.graphics.getShader():send("modelMatrix", data.model)
love.graphics.draw(data.mesh)
end

self.transparentMeshes = {}
end

return World

0 comments on commit 8ca8b7e

Please sign in to comment.