render/render.lua
2026-03-20 22:24:10 +01:00

530 lines
13 KiB
Lua

local fps = 0
local math_floor = math.floor
local time = 0
local function ClearBuffers(meta, colorbuffer, depthbuffer, color, depth)
local i
for i = 0, meta[3] - 1 do
colorbuffer[1 + i * 3] = color[1]
colorbuffer[1 + i * 3 + 1] = color[2]
colorbuffer[1 + i * 3 + 2] = color[3]
depthbuffer[1 + i] = depth
end
end
local function DegToRad(deg)
local rad
rad = deg * 0.0174532925
return rad
end
local function Min(a, b)
local r
if a < b then
r = a
else
r = b
end
return r
end
local function Min3(a, b, c)
local r
r = Min(Min(a, b), c)
return r
end
local function Max(a, b)
local r
if a > b then
r = a
else
r = b
end
return r
end
local function Max3(a, b, c)
local r
r = Max(Max(a, b), c)
return r
end
local function IsOnRight(a, b, c)
local r
if (b[1] - a[1]) * (c[2] - a[2]) - (b[2] - a[2]) * (c[1] - a[1]) <= 0 then
r = true
else
r = false
end
return r
end
local function Distance2(a, b)
local x, y, d
x = b[1] - a[1]
y = b[2] - a[2]
d = math.sqrt(x * x + y * y)
return d
end
local function Normalize(a)
local l
l = math.sqrt(a[1] * a[1] + a[2] * a[2] + a[3] * a[3])
a[1] = a[1] / l
a[2] = a[2] / l
a[3] = a[3] / l
end
local function MapToRes(meta, a)
a[1] = a[1] / a[4]
a[2] = a[2] / a[4]
a[3] = a[3] / a[4]
a[1] = (a[1] + 1.0) * 0.5 * (meta[1] - 1)
a[2] = (1.0 - a[2]) * 0.5 * (meta[2] - 1)
end
local function Cross(result, a, b)
result[1] = a[2] * b[3] - a[3] * b[2]
result[2] = a[3] * b[1] - a[1] * b[3]
result[3] = a[1] * b[2] - a[2] * b[1]
end
local function Dot(a, b)
local result
result = a[1] * b[1] + a[2] * b[2] + a[3] * b[3]
return result
end
local function Dot2(a, b)
local result
result = a[1] * b[1] + a[2] * b[2]
return result
end
local function VecCopy3(result, a)
result[1] = a[1]
result[2] = a[2]
result[3] = a[3]
end
local function VecSubVec3(result, a, b)
result[1] = a[1] - b[1]
result[2] = a[2] - b[2]
result[3] = a[3] - b[3]
end
local function MatMultMat(result, a, b)
result[1] = a[1] * b[1] + a[2] * b[5] + a[3] * b[9] + a[4] * b[13]
result[2] = a[1] * b[2] + a[2] * b[6] + a[3] * b[10] + a[4] * b[14]
result[3] = a[1] * b[3] + a[2] * b[7] + a[3] * b[11] + a[4] * b[15]
result[4] = a[1] * b[4] + a[2] * b[8] + a[3] * b[12] + a[4] * b[16]
result[5] = a[5] * b[1] + a[6] * b[5] + a[7] * b[9] + a[8] * b[13]
result[6] = a[5] * b[2] + a[6] * b[6] + a[7] * b[10] + a[8] * b[14]
result[7] = a[5] * b[3] + a[6] * b[7] + a[7] * b[11] + a[8] * b[15]
result[8] = a[5] * b[4] + a[6] * b[8] + a[7] * b[12] + a[8] * b[16]
result[9] = a[9] * b[1] + a[10] * b[5] + a[11] * b[9] + a[12] * b[13]
result[10] = a[9] * b[2] + a[10] * b[6] + a[11] * b[10] + a[12] * b[14]
result[11] = a[9] * b[3] + a[10] * b[7] + a[11] * b[11] + a[12] * b[15]
result[12] = a[9] * b[4] + a[10] * b[8] + a[11] * b[12] + a[12] * b[16]
result[13] = a[13] * b[1] + a[14] * b[5] + a[15] * b[9] + a[16] * b[13]
result[14] = a[13] * b[2] + a[14] * b[6] + a[15] * b[10] + a[16] * b[14]
result[15] = a[13] * b[3] + a[14] * b[7] + a[15] * b[11] + a[16] * b[15]
result[16] = a[13] * b[4] + a[14] * b[8] + a[15] * b[12] + a[16] * b[16]
end
local function MatMultVec(result, a, v)
result[1] = a[1] * v[1] + a[2] * v[2] + a[3] * v[3] + a[4] * v[4]
result[2] = a[5] * v[1] + a[6] * v[2] + a[7] * v[3] + a[8] * v[4]
result[3] = a[9] * v[1] + a[10] * v[2] + a[11] * v[3] + a[12] * v[4]
result[4] = a[13] * v[1] + a[14] * v[2] + a[15] * v[3] + a[16] * v[4]
end
local function MatMultVec3(result, a, v)
result[1] = a[1] * v[1] + a[2] * v[2] + a[3] * v[3] + a[4]
result[2] = a[5] * v[1] + a[6] * v[2] + a[7] * v[3] + a[8]
result[3] = a[9] * v[1] + a[10] * v[2] + a[11] * v[3] + a[12]
result[4] = a[13] * v[1] + a[14] * v[2] + a[15] * v[3] + a[16]
end
local function LookAt(mat, campos, targetpos, upvec)
local forward = {}
local right = {}
local up = {}
VecSubVec3(forward, targetpos, campos)
Normalize(forward)
Cross(right, forward, upvec)
Normalize(right)
Cross(up, right, forward)
mat[1] = right[1]
mat[2] = right[2]
mat[3] = right[3]
mat[4] = -Dot(right, campos)
mat[5] = up[1]
mat[6] = up[2]
mat[7] = up[3]
mat[8] = -Dot(up, campos)
mat[9] = -forward[1]
mat[10] = -forward[2]
mat[11] = -forward[3]
mat[12] = Dot(forward, campos)
mat[13] = 0.0
mat[14] = 0.0
mat[15] = 0.0
mat[16] = 1.0
end
local function Perspective(mat, fov, aspectratio, near, far)
local tanhalffovy
tanhalffovy = math.tan(fov * 0.5)
mat[1] = 1 / (aspectratio * tanhalffovy)
mat[2] = 0.0
mat[3] = 0.0
mat[4] = 0.0
mat[5] = 0.0
mat[6] = 1 / tanhalffovy
mat[7] = 0.0
mat[8] = 0.0
mat[9] = 0.0
mat[10] = 0.0
mat[11] = -(far + near) / (far - near)
mat[12] = -(2 * far * near) / (far - near)
mat[13] = 0.0
mat[14] = 0.0
mat[15] = -1.0
mat[16] = 0.0
end
local function OutputVT100(meta, colorbuffer)
print("\x1b[1;1H")
local r1, g1, b1, r2, b2, g2, width, height, idx, rowoffset
width = meta[1]
height = meta[2]
local out = {}
local pr1, pg1, pb1, pr2, pg2, pb2 = 0, 0, 0, 0, 0, 0
for y = 0, height - 2, 2 do
table.insert(out, "\n")
for x = 0, width - 1 do
idx = (x + y * width) * 3
rowoffset = width * 3
r1 = math_floor(colorbuffer[1 + idx] * 255)
g1 = math_floor(colorbuffer[1 + idx + 1] * 255)
b1 = math_floor(colorbuffer[1 + idx + 2] * 255)
r2 = math_floor(colorbuffer[1 + idx + rowoffset] * 255)
g2 = math_floor(colorbuffer[1 + idx + 1 + rowoffset] * 255)
b2 = math_floor(colorbuffer[1 + idx + 2 + rowoffset] * 255)
if r1 == pr1 and g1 == pg1 and b1 == pb1 and r2 == pr2 and g2 == pg2 and b2 == pb2 then
table.insert(out, "\xDF")
else
pr1, pg1, pb1, pr2, pg2, pb2 = r1, g1, b1, r2, g2, b2
table.insert(out, string.format("\x1b[38;2;%d;%d;%dm\x1b[48;2;%d;%d;%dm\xDF", r1, g1, b1, r2, g2, b2))
end
-- io.write("\x1b[38;2;" ..
-- r1 .. ";" .. g1 .. ";" .. b1 .. "m" .. "\x1b[48;2;" .. r2 .. ";" .. g2 .. ";" .. b2 .. "m" .. "\xDF")
end
end
io.write(table.concat(out))
io.write(string.format("\n\x1b[38;2;255;255;255m\x1b[48;2;0;0;0m%d FPS", fps))
end
local function DrawTriangle(meta, colorbuffer, depthbuffer, wp0, wp1, wp2, texture, c0, c1, c2, mvp, lightdir, n0, n1, n2)
local p0 = {}
local p1 = {}
local p2 = {}
MatMultVec3(p0, mvp, wp0)
MatMultVec3(p1, mvp, wp1)
MatMultVec3(p2, mvp, wp2)
if p0[4] ~= 0.0 and p1[4] ~= 0.0 and p2[4] ~= 0.0 then
MapToRes(meta, p0)
MapToRes(meta, p1)
MapToRes(meta, p2)
local aabbmin = {}
local aabbmax = {}
aabbmin[1] = Max(Min3(p0[1], p1[1], p2[1]), 0)
aabbmin[2] = Max(Min3(p0[2], p1[2], p2[2]), 0)
aabbmax[1] = Min(Max3(p0[1], p1[1], p2[1]), meta[1] - 1)
aabbmax[2] = Min(Max3(p0[2], p1[2], p2[2]), meta[2] - 1)
local idx, tx, ty, ti
local p = {}
local depth
local w0, w1, w2, dot00, dot01, dot11, dot20, dot21, denom, d0, d1, d2
local v0 = {}
local v1 = {}
local v2 = {}
local texcoord = {}
local normal = {}
local diff
for y = math_floor(aabbmin[2]), math_floor(aabbmax[2]) do
for x = math_floor(aabbmin[1]), math_floor(aabbmax[1]) do
p[1] = x
p[2] = y
if IsOnRight(p0, p1, p) and IsOnRight(p1, p2, p) and IsOnRight(p2, p0, p) then
v0[1] = p1[1] - p0[1]
v0[2] = p1[2] - p0[2]
v1[1] = p2[1] - p0[1]
v1[2] = p2[2] - p0[2]
v2[1] = p[1] - p0[1]
v2[2] = p[2] - p0[2]
dot00 = Dot2(v0, v0)
dot01 = Dot2(v0, v1)
dot11 = Dot2(v1, v1)
dot20 = Dot2(v2, v0)
dot21 = Dot2(v2, v1)
denom = dot00 * dot11 - dot01 * dot01
w1 = (dot11 * dot20 - dot01 * dot21) / denom
w2 = (dot00 * dot21 - dot01 * dot20) / denom
w0 = 1.0 - w1 - w2
depth = p0[3] * w0 + p1[3] * w1 + p2[3] * w2
idx = math_floor(x) + meta[1] * math_floor(y)
if depth > 0.0 and depthbuffer[1 + idx] > depth then
depthbuffer[1 + idx] = depth
idx = idx * 3
texcoord[1] = w0 * c0[1] + w1 * c1[1] + w2 * c2[1]
texcoord[2] = w0 * c0[2] + w1 * c1[2] + w2 * c2[2]
normal[1] = w0 * n0[1] + w1 * n1[1] + w2 * n2[1]
normal[2] = w0 * n0[2] + w1 * n1[2] + w2 * n2[2]
normal[3] = w0 * n0[3] + w1 * n1[3] + w2 * n2[3]
Normalize(normal)
diff = Max(0.5, Dot(normal, lightdir))
tx = math_floor(texcoord[1] * meta[4])
ty = math_floor((1 - texcoord[2]) * meta[5])
ti = (tx + ty * meta[4]) * 3
-- uz ne kokote
colorbuffer[1 + idx] = texture[1 + ti] / 255 * diff
colorbuffer[1 + idx + 1] = texture[1 + ti + 1] / 255 * diff
colorbuffer[1 + idx + 2] = texture[1 + ti + 2] / 255 * diff
OutputVT100(meta, colorbuffer)
end
end
end
end
end
end
local file = io.open("data.txt", "r")
local function Input()
return file:read("*n")
end
-- file:close() -- Close the file
-- return number
local function Main()
os.execute(" ")
local meta = {}
-- meta[1] = 175
-- meta[2] = 120
meta[1] = 175 * 2
meta[2] = 120 * 2
meta[3] = meta[1] * meta[2]
local depthbuffer = {}
local colorbuffer = {}
local background = {}
background[1] = 0.3
background[2] = 0.3
background[3] = 0.3
ClearBuffers(meta, colorbuffer, depthbuffer, background, 100.0)
local lightdir = {}
lightdir[1] = .3
lightdir[2] = 1
lightdir[3] = .4
Normalize(lightdir)
local view = {}
local proj = {}
local mvp = {}
local campos = {}
local targetpos = {}
local upvector = {}
targetpos[1] = 0
targetpos[2] = 0
targetpos[3] = 0
upvector[1] = 0
upvector[2] = 1
upvector[3] = 0
local aspectratio
aspectratio = 1.46
Perspective(proj, DegToRad(90.0) / aspectratio, aspectratio, 0.1, 50.0)
local p0 = {}
local p1 = {}
local p2 = {}
local c0 = {}
local c1 = {}
local c2 = {}
local n0 = {}
local n1 = {}
local n2 = {}
local datasize, i, vertices
datasize = Input()
vertices = Input()
local data = {}
for i = 1, datasize do
data[i] = Input()
end
print("model rdy")
meta[4] = Input()
meta[5] = Input()
local tp
tp = meta[4] * meta[5] * 3
local texture = {}
for i = 0, tp - 1 do
texture[1 + i] = Input()
end
print("textura rdy")
local temp
local i0, i1, i2
local camangle
camangle = 0
local frames = 0
local lastframereset = 0
while true do
frames = frames + 1
time = os.clock() * 1000
if time > lastframereset + 1000 then
fps = frames
frames = 0
lastframereset = time
end
ClearBuffers(meta, colorbuffer, depthbuffer, background, 100.0)
local camdis
camdis = 7.0
campos[1] = math.sin(camangle) * camdis
campos[2] = 0.8 * camdis
campos[3] = math.cos(camangle) * camdis
camangle = time * 0.0003
LookAt(view, campos, targetpos, upvector)
MatMultMat(mvp, proj, view)
for i = 0, vertices - 3, 3 do
i0 = i * 8
i1 = (i + 1) * 8
i2 = (i + 2) * 8
p0[1] = data[1 + i0]
p0[2] = data[1 + i0 + 1]
p0[3] = data[1 + i0 + 2]
p1[1] = data[1 + i1]
p1[2] = data[1 + i1 + 1]
p1[3] = data[1 + i1 + 2]
p2[1] = data[1 + i2]
p2[2] = data[1 + i2 + 1]
p2[3] = data[1 + i2 + 2]
c0[1] = data[1 + i0 + 3]
c0[2] = data[1 + i0 + 4]
c1[1] = data[1 + i1 + 3]
c1[2] = data[1 + i1 + 4]
c2[1] = data[1 + i2 + 3]
c2[2] = data[1 + i2 + 4]
n0[1] = data[1 + i0 + 5]
n0[2] = data[1 + i0 + 6]
n0[3] = data[1 + i0 + 7]
n1[1] = data[1 + i1 + 5]
n1[2] = data[1 + i1 + 6]
n1[3] = data[1 + i1 + 7]
n2[1] = data[1 + i2 + 5]
n2[2] = data[1 + i2 + 6]
n2[3] = data[1 + i2 + 7]
DrawTriangle(meta, colorbuffer, depthbuffer, p0, p1, p2, texture, c0, c1, c2, mvp, lightdir, n0, n1, n2)
end
OutputVT100(meta, colorbuffer)
end
end
Main()