Compare commits

..

No commits in common. "50188813f8f017d297ad1cd5fc822402dde9fb82" and "094847cacac06d460b9af4e404ebef74d6df50c0" have entirely different histories.

54 changed files with 497 additions and 2070 deletions

1
.gitignore vendored
View File

@ -7,4 +7,3 @@ main
*.so
*.dylib
__pycache__
minecraft/region*.lights.vtx

View File

@ -19,9 +19,7 @@ LDFLAGS += $(shell pkg-config --libs glfw3)
OBJS = \
src/gl.o \
src/opengl.o \
src/test.o \
src/font.o \
src/window.o
src/test.o
all: test.so

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -8,12 +8,3 @@ short index_buffer_configuration_offsets[] = {
768, 780, 798, 816, 840, 858, 882, 906,
936, 954, 978, 1002, 1032, 1056, 1086, 1116,
};
struct {
short offset;
short count;
} index_buffer_custom_offsets[] = {
{1152, 12}, // tallgrass.obj
{1164, 36}, // fence.obj
{1200, 36}, // torch.obj
{1236, 24}, // wheat.obj
};

View File

@ -1,68 +0,0 @@
#pragma once
namespace font {
struct font_desc {
char const * const path;
int const texture_width;
int const texture_height;
int const glyph_width;
int const glyph_height;
};
font_desc const terminus[] = {
{
.path = "font/terminus_128x64_6x12.data",
.texture_width = 128,
.texture_height = 64,
.glyph_width = 6,
.glyph_height = 12,
},
{
.path = "font/terminus_128x128_8x16.data",
.texture_width = 128,
.texture_height = 128,
.glyph_width = 8,
.glyph_height = 16,
},
{
.path = "font/terminus_256x128_10x18.data",
.texture_width = 256,
.texture_height = 128,
.glyph_width = 10,
.glyph_height = 18,
},
{
.path = "font/terminus_256x128_12x24.data",
.texture_width = 256,
.texture_height = 128,
.glyph_width = 12,
.glyph_height = 24,
},
{
.path = "font/terminus_256x256_16x32.data",
.texture_width = 256,
.texture_height = 256,
.glyph_width = 16,
.glyph_height = 32,
},
};
int const terminus_length = (sizeof (terminus)) / (sizeof (font_desc));
struct font {
font_desc const * desc;
unsigned int texture;
int stride;
struct {
float width;
float height;
} cell;
};
void load_shader();
font load_font(font_desc const& desc);
void load_fonts(font * const fonts, font_desc const * const descs, int length);
int best_font(font_desc const * const descs, int length);
void draw_start(font const& font, unsigned int vertex_array_object, unsigned int index_buffer);
void draw_string(font const& font, char const * const s, int x, int y);
}

View File

@ -4,9 +4,6 @@
extern "C" {
#endif
extern char const * g_source_path;
extern int g_source_path_length;
void * read_file(const char * filename, int * out_size);
unsigned int compile_from_files(const char * vertex_path,

View File

@ -4,11 +4,9 @@
extern "C" {
#endif
void load(const char * source_path);
void load();
void draw();
void update(float lx, float ly, float rx, float ry, float tl, float tr,
int up, int down, int left, int right,
int a, int b, int x, int y);
void update(float lx, float ly, float ry);
#ifdef __cplusplus
}

View File

@ -1,13 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
extern float g_window_width;
extern float g_window_height;
void update_window(int width, int height);
#ifdef __cplusplus
}
#endif

View File

@ -5,36 +5,21 @@ function init()
joysticks = love.joystick.getJoysticks()
ffi.cdef[[
void load(const char * source_path);
void update_window(int width, int height);
void load();
void draw();
void update(float lx, float ly, float rx, float ry, float tl, float tr,
int up, int down, int left, int right,
int a, int b, int x, int y);
void update(float lx, float ly, float ry);
]]
local source_path = love.filesystem.getSource()
test = ffi.load(source_path .. "/test.so")
test.load(source_path)
print(love.filesystem.getWorkingDirectory())
test = ffi.load("./test.so")
test.load()
end
local update = function(dt)
for _, joystick in ipairs(joysticks) do
local lx = joystick:getGamepadAxis("leftx")
local ly = joystick:getGamepadAxis("lefty")
local rx = joystick:getGamepadAxis("rightx")
local ry = joystick:getGamepadAxis("righty")
local tl = joystick:getGamepadAxis("triggerleft")
local tr = joystick:getGamepadAxis("triggerright")
local up = joystick:isGamepadDown("dpup")
local down = joystick:isGamepadDown("dpdown")
local left = joystick:isGamepadDown("dpleft")
local right = joystick:isGamepadDown("dpright")
local a = joystick:isGamepadDown("a")
local b = joystick:isGamepadDown("b")
local x = joystick:isGamepadDown("x")
local y = joystick:isGamepadDown("y")
test.update(lx, ly, rx, ry, tl, tr, up, down, left, right, a, b, x, y)
test.update(lx, ly, ry)
end
end
@ -57,12 +42,6 @@ function love.run()
end
end
local width
local height
local flags
width, height, flags = love.window.getMode()
test.update_window(width, height)
local dt = love.timer.step()
update(dt)
@ -71,6 +50,6 @@ function love.run()
love.graphics.present()
love.timer.sleep(0.001)
local fps = love.timer.getFPS( )
--print(fps)
print(fps)
end
end

Binary file not shown.

View File

@ -1,13 +1,106 @@
import struct
import data
import sys
unk = 253
def id_to_px(i):
x = i % 16
y = i // 16
return x * 16, y * 16
with open(sys.argv[1], "wb") as f:
def px_to_id(px, py):
x = px // 16
y = py // 16
i = y * 16 + x
return i
unk = 185
mapping = [
(1, 1, "stone"),
(2, 0, "grass"),
(31, 0, "grass"), # fixme actually tallgrass
(3, 2, "dirt"),
(4, 16, "stonebrick"),
(5, 4, "wood"),
(6, 15, "sapling"),
(7, 17, "bedrock"),
(8, 205, "water"), # flowing
(9, 205, "water"), # still
(10, 237, "lava"), # flowing
(11, 237, "lava"), # still
(12, 18, "sand"),
(13, 19, "gravel"),
(14, 32, "oreGold"),
(15, 33, "oreIron"),
(16, 34, "oreCoal"),
(17, 20, "log"),
(18, 52, "leaves"),
(19, 48, "sponge"),
(20, 49, "glass"),
(35, 64, "cloth"),
(37, 13, "flower"),
(38, 12, "rose"),
(39, 29, "mushroom"),
(40, 28, "mushroom"),
(41, 39, "blockGold"),
(42, 38, "blockIron"),
(43, 5, "stoneSlab"), # double
(44, 5, "stoneSlab"), # single
(45, 7, "brick"),
(46, 8, "tnt"),
(47, 35, "bookshelf"),
(48, 36, "stoneMoss"),
(49, 37, "obsidian"),
(50, 80, "torch"),
(51, 31, "fire"),
(52, 65, "mobSpawner"),
(53, 4, "stairsWood"),
(54, 27, "chest"),
(55, 84, "redstoneDust"),
(56, 50, "oreDiamond"),
(57, 40, "blockDiamond"),
(58, 43, "workbench"),
(59, 88, "crops"),
(60, 87, "farmland"),
(61, 44, "furnace"), # off
(62, 61, "furnace"), # burning
(63, unk, "sign"),
(64, 81, "doorWood"),
(65, 83, "ladder"),
(66, 128, "rail"),
(67, 16, "stairsStone"),
(68, unk, "sign"),
(69, 96, "lever"),
(70, 6, "pressurePlate"),
(71, 82, "doorIron"),
(72, 6, "pressurePlate"),
(73, 51, "oreRedstone"),
(74, 51, "oreRedstone"),
(75, 115, "notGate"),
(76, 99, "notGate"),
(77, unk, "button"),
(78, 66, "snow"),
(79, 67, "ice"),
(80, 66, "snow"),
(81, 70, "cactus"),
(82, 72, "clay"),
(83, 73, "reeds"),
(84, 74, "jukebox"),
(85, 4, "fence"),
(86, 102, "pumpkin"),
(87, 103, "hellrock"),
(88, 104, "hellsand"),
(89, 105, "lightgem"),
(90, 14, "portal"),
(91, 102, "pumpkin"),
]
lookup = {
k: v for k, v, _ in mapping
}
with open("block_id_to_texture_id.data", "wb") as f:
for i in range(256):
if i in data.tiles_by_id:
value = data.tiles_by_id[i].texture
else:
value = unk
value = lookup.get(i, unk)
f.write(struct.pack("<i", value))
print(str(value).rjust(3), end=', ')
if i % 16 == 15:
print()

View File

@ -1,4 +0,0 @@
set -eux
cd ./minecraft/gen
PYTHON=pypy3.11
$PYTHON blocks.py ../block_id_to_texture_id.data

View File

@ -1,36 +0,0 @@
# Blender 5.0.0
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vt -0.000000 0.000000
vt 1.000000 -0.000000
s 0
f 5/1/1 3/2/1 1/3/1
f 3/4/2 8/5/2 4/6/2
f 7/4/3 6/5/3 8/6/3
f 2/1/4 8/2/4 6/3/4
f 1/4/5 4/5/5 2/6/5
f 5/4/6 2/5/6 6/6/6
f 5/1/1 7/4/1 3/2/1
f 3/4/2 7/2/2 8/5/2
f 7/4/3 5/2/3 6/5/3
f 2/1/4 4/4/4 8/2/4
f 1/4/5 3/2/5 4/5/5
f 5/4/6 1/2/6 2/5/6

134
minecraft/gen/cube.py Normal file
View File

@ -0,0 +1,134 @@
positions = [
(1.0, 1.0, -1.0),
(1.0, -1.0, -1.0),
(1.0, 1.0, 1.0),
(1.0, -1.0, 1.0),
(-1.0, 1.0, -1.0),
(-1.0, -1.0, -1.0),
(-1.0, 1.0, 1.0),
(-1.0, -1.0, 1.0)
]
normals = [
(0.0, 1.0, 0.0),
(0.0, 0.0, 1.0),
(-1.0, 0.0, 0.0),
(0.0, -1.0, 0.0),
(1.0, 0.0, 0.0),
(0.0, 0.0, -1.0),
]
textures = [
(1.0, 0.0),
(0.0, 1.0),
(0.0, 0.0),
(1.0, 1.0),
(0.0, 0.0),
(1.0, 0.0),
]
indices = [
[
[4, 0, 0],
[2, 1, 0],
[0, 2, 0],
],
[
[2, 3, 1],
[7, 4, 1],
[3, 5, 1],
],
[
[6, 3, 2],
[5, 4, 2],
[7, 5, 2],
],
[
[1, 0, 3],
[7, 1, 3],
[5, 2, 3],
],
[
[0, 3, 4],
[3, 4, 4],
[1, 5, 4],
],
[
[4, 3, 5],
[1, 4, 5],
[5, 5, 5],
],
[
[4, 0, 0],
[6, 3, 0],
[2, 1, 0],
],
[
[2, 3, 1],
[6, 1, 1],
[7, 4, 1],
],
[
[6, 3, 2],
[4, 1, 2],
[5, 4, 2],
],
[
[1, 0, 3],
[3, 3, 3],
[7, 1, 3],
],
[
[0, 3, 4],
[2, 1, 4],
[3, 4, 4],
],
[
[4, 3, 5],
[0, 1, 5],
[1, 4, 5],
],
]
vertex_buffer = []
index_buffer = []
index_lookup = {}
for triangle in indices:
for p_ix, t_ix, n_ix in triangle:
key = (p_ix, n_ix, t_ix)
if key not in index_lookup:
position = positions[p_ix]
normal = normals[n_ix]
texture = textures[t_ix]
index = len(vertex_buffer)
index_lookup[key] = index
vertex_buffer.append((tuple(position),
tuple(normal),
tuple(texture)))
index_buffer.append(index_lookup[key])
def gen():
for position, normal, texture in vertex_buffer:
p = ", ".join(map(str, map(float, position)))
n = ", ".join(map(str, map(float, normal)))
t = ", ".join(map(str, map(float, texture)))
print(f"vertex_t(vec3({p}), vec3({n}), vec2({t})),")
for i in range(len(index_buffer) // 3):
tri = ", ".join(str(index_buffer[i * 3 + n]) for n in range(3))
print(f"{tri},")
from collections import defaultdict
by_normal = defaultdict(list)
for i in range(len(index_buffer) // 3):
tri = [index_buffer[i * 3 + n] for n in range(3)]
s = set(vertex_buffer[j][1] for j in tri)
assert len(s) == 1
normal, = iter(s)
by_normal[normal].append(tri)
from pprint import pprint
pprint(dict(by_normal))
pprint(vertex_buffer)

View File

@ -1,364 +0,0 @@
from dataclasses import dataclass
class BlockID:
AIR = 0
STONE = 1
GRASS = 2
DIRT = 3
STONEBRICK = 4
WOOD = 5
SAPLING = 6
BEDROCK = 7
WATER = 8
WATER_CALM = 9
LAVA = 10
LAVA_CALM = 11
SAND = 12
GRAVEL = 13
ORE_GOLD = 14
ORE_IRON = 15
ORE_COAL = 16
TREE_TRUNK = 17
LEAVES = 18
SPONGE = 19
GLASS = 20
ORE_LAPIS = 21
BLOCK_LAPIS = 22
DISPENSER = 23
SANDSTONE = 24
NOTE_BLOCK = 25
BED = 26
RAIL_POWERED = 27
RAIL_ACTIVATOR = 28
PISTON_STICKY = 29
COBWEB = 30
TALL_GRASS = 31
DEAD_BUSH = 32
PISTON = 33
PISTON_HEAD = 34
CLOTH = 35
PISTON_MOVING = 36
FLOWER = 37
ROSE = 38
MUSHROOM_1 = 39
MUSHROOM_2 = 40
BLOCK_GOLD = 41
BLOCK_IRON = 42
STONESLAB_FULL = 43
STONESLAB_HALF = 44
BRICKS = 45
TNT = 46
BOOKSHELF = 47
MOSS_STONE = 48
OBSIDIAN = 49
TORCH = 50
FIRE = 51
SPAWNER = 52
STAIRS_WOOD = 53
CHEST = 54
WIRE = 55
ORE_EMERALD = 56
BLOCK_EMERALD = 57
WORKBENCH = 58
WHEAT = 59
FARMLAND = 60
FURNACE = 61
FURNACE_LIT = 62
SIGN = 63
DOOR_WOOD = 64
LADDER = 65
RAIL = 66
STAIRS_STONE = 67
SIGN_WALL = 68
LEVER = 69
PLATE_STONE = 70
DOOR_IRON = 71
PLATE_WOOD = 72
ORE_REDSTONE = 73
ORE_REDSTONE_LIT = 74
NOT_GATE_OFF = 75
NOT_GATE_ON = 76
BUTTON_STONE = 77
TOPSNOW = 78
ICE = 79
SNOW = 80
CACTUS = 81
CLAY = 82
REEDS = 83
JUKEBOX = 84
FENCE = 85
PUMPKIN = 86
NETHERRACK = 87
SOUL_SAND = 88
GLOWSTONE = 89
PORTAL = 90
PUMPKIN_LIT = 91
CAKE = 92
REPEATER_OFF = 93
REPEATER_ON = 94
INVISIBLE = 95
TRAPDOOR = 96
STONE_MONSTER_EGG = 97
STONE_BRICKS = 98
MUSHROOM1_BLOCK = 99
MUSHROOM2_BLOCK = 100
CLOTH_00 = 101
CLOTH_10 = 102
CLOTH_20 = 103
CLOTH_30 = 104
CLOTH_40 = 105
CLOTH_50 = 106
CLOTH_60 = 107
CLOTH_70 = 108
CLOTH_01 = 109
CLOTH_11 = 110
CLOTH_21 = 111
CLOTH_31 = 112
CLOTH_41 = 113
CLOTH_51 = 114
CLOTH_61 = 115
# modded
YELLOW_COBBLE = 128
MARBLE_YELLOW = 248
class Texture:
GRASS_TOP = 0
STONE = 1
DIRT = 2
GRASS_SIDE = 3
PLANKS = 4
STONE_SLAB_SIDE = 5
STONE_SLAB_TOP = 6
BRICKS = 7
TNT_SIDE = 8
TNT_TOP = 9
TNT_BOTTOM = 10
COBWEB = 11
ROSE = 12
FLOWER = 13
WATER_STATIC = 14
SAPLING = 15
STONEBRICK = 16
BEDROCK = 17
SAND = 18
GRAVEL = 19
LOG_SIDE = 20
LOG_TOP = 21
IRON = 22
GOLD = 23
EMERALD = 24
CHEST_ONE_TOP = 25
CHEST_ONE_SIDE = 26
CHEST_ONE_FRONT = 27
MUSHROOM_RED = 28
MUSHROOM_BROWN = 29
OBSIDIAN_CRYING = 30
FIRE1 = 31
ORE_GOLD = 32
ORE_IRON = 33
ORE_COAL = 34
BOOKSHELF = 35
MOSSY_STONE = 36
OBSIDIAN = 37
GRASS_SIDE_OVERLAY = 38
TALL_GRASS = 39
NONE40 = 40
CHEST_TWO_FRONT_LEFT = 41
CHEST_TWO_FRONT_RIGHT = 42
WORKBENCH_TOP = 43
FURNACE_FRONT = 44
FURNACE_SIDE = 45
DISPENSER_SIDE = 46
FIRE2 = 47
SPONGE = 48
GLASS = 49
ORE_EMERALD = 50
ORE_RED_STONE = 51
LEAVES_TRANSPARENT = 52
LEAVES_OPAQUE = 53
NONE54 = 54
DEAD_BUSH = 55
NONE56 = 56
CHEST_TWO_BACK_LEFT = 57
CHEST_TWO_BACK_RIGHT = 58
WORKBENCH_SIDE_1 = 59
WORKBENCH_SIDE_2 = 60
FURNACE_LIT = 61
FURNACE_TOP = 62
NONE63 = 63
CLOTH_64 = 64
SPAWNER = 65
SNOW = 66
ICE = 67
GRASS_SIDE_SNOW = 68
CACTUS_TOP = 69
CACTUS_SIDE = 70
CACTUS_BOTTOM = 71
CLAY = 72
REEDS = 73
JUKEBOX_SIDE = 74
JUKEBOX_TOP = 75
NONE76 = 76
NONE77 = 77
NONE78 = 78
NONE79 = 79
TORCH_LIT = 80
DOOR_TOP = 81
DOOR_IRON_TOP = 82
LADDER = 83
TRAPDOOR = 84
NONE85 = 85
FARMLAND = 86
FARMLAND_DRY = 87
WHEAT_0 = 88
WHEAT_1 = 89
WHEAT_2 = 90
WHEAT_3 = 91
WHEAT_4 = 92
WHEAT_5 = 93
WHEAT_6 = 94
WHEAT_7 = 95
LEVER = 96
DOOR_BOTTOM = 97
DOOR_IRON_BOTTOM = 98
TORCH_RED_STONE = 99
NONE100 = 100
NONE101 = 101
PUMPKIN_TOP = 102
BLOODSTONE = 103
SOULSAND = 104
GLOWSTONE = 105
STICKY_PISTON = 106
PISTON = 107
NONE108 = 108
NONE109 = 109
NONE110 = 110
NONE111 = 111
RAIL_CURVED = 112
CLOTH_112 = 113
CLOTH_113 = 114
TORCH_RED_STONE_OFF = 115
LOG_SPRUCE = 116
LOG_BIRCH = 117
PUMPKIN_SIDE = 118
PUMPKIN_FACE = 119
PUMPKIN_FACE_LIT = 120
CAKE_TOP = 121
CAKE_SIDE = 122
CAKE_SIDE_BIT = 123
CAKE_BOTTOM = 124
NONE125 = 125
NONE126 = 126
NONE127 = 127
RAIL = 128
LAPIS = 144
ORE_LAPIS = 160
POWERED_RAIL = 163
REDSTONE_DUST = 164
REDSTONE_DUST_LINE = 165
DETECTOR_RAIL = 195
SANDSTONE_TOP = 176
SANDSTONE_SIDE = 192
WATER = 205
SANDSTONE_BOTTOM = 208
LAVA = 237
INFO_UPDATEGAME1 = 252
INFO_UPDATEGAME2 = 253
LAVA_PLACEHOLDER = 255
# modded
YELLOW_COBBLE = 213
MARBLE_YELLOW = 214
@dataclass
class Tile:
block_id: BlockID
texture: Texture
tiles = [
Tile(BlockID.STONE, Texture.STONE),
Tile(BlockID.GRASS, Texture.GRASS_TOP), # fixme
Tile(BlockID.DIRT, Texture.DIRT),
Tile(BlockID.STONEBRICK, Texture.STONEBRICK),
Tile(BlockID.WOOD, Texture.PLANKS),
Tile(BlockID.BEDROCK, Texture.BEDROCK),
Tile(BlockID.WATER, Texture.WATER), # fixme
Tile(BlockID.WATER_CALM, Texture.WATER), # fixme
Tile(BlockID.LAVA, Texture.LAVA), # fixme
Tile(BlockID.LAVA_CALM, Texture.LAVA), # fixme
Tile(BlockID.SAND, Texture.SAND),
Tile(BlockID.GRAVEL, Texture.GRAVEL),
Tile(BlockID.ORE_GOLD, Texture.ORE_GOLD),
Tile(BlockID.ORE_IRON, Texture.ORE_IRON),
Tile(BlockID.ORE_COAL, Texture.ORE_COAL),
Tile(BlockID.TREE_TRUNK, Texture.LOG_SIDE), # fixme
Tile(BlockID.LEAVES, Texture.LEAVES_TRANSPARENT), # fixme
Tile(BlockID.GLASS, Texture.GLASS),
Tile(BlockID.ORE_LAPIS, Texture.ORE_LAPIS),
Tile(BlockID.BLOCK_LAPIS, Texture.LAPIS),
Tile(BlockID.SANDSTONE, Texture.SANDSTONE_SIDE),
Tile(BlockID.CLOTH, Texture.CLOTH_64), # wool, colored
Tile(BlockID.FLOWER, Texture.FLOWER),
Tile(BlockID.ROSE, Texture.ROSE),
Tile(BlockID.MUSHROOM_1, Texture.MUSHROOM_BROWN),
Tile(BlockID.MUSHROOM_2, Texture.MUSHROOM_RED),
Tile(BlockID.BLOCK_GOLD, Texture.GOLD),
Tile(BlockID.BLOCK_IRON, Texture.IRON),
Tile(BlockID.STONESLAB_FULL, Texture.STONE_SLAB_SIDE), # fixme
Tile(BlockID.STONESLAB_HALF, Texture.STONE_SLAB_SIDE), # fixme
Tile(BlockID.BRICKS, Texture.BRICKS),
Tile(BlockID.TNT, Texture.TNT_SIDE),
Tile(BlockID.BOOKSHELF, Texture.BOOKSHELF),
Tile(BlockID.MOSS_STONE, Texture.MOSSY_STONE),
Tile(BlockID.OBSIDIAN, Texture.OBSIDIAN),
Tile(BlockID.TORCH, Texture.TORCH_LIT),
Tile(BlockID.STAIRS_WOOD, Texture.PLANKS), # fixme
Tile(BlockID.WIRE, Texture.REDSTONE_DUST),
Tile(BlockID.ORE_EMERALD, Texture.ORE_EMERALD),
Tile(BlockID.BLOCK_EMERALD, Texture.EMERALD),
Tile(BlockID.FARMLAND, Texture.FARMLAND), # fixme
Tile(BlockID.DOOR_WOOD, Texture.DOOR_TOP), # fixme
Tile(BlockID.LADDER, Texture.LADDER),
Tile(BlockID.STAIRS_STONE, Texture.STONEBRICK),
Tile(BlockID.DOOR_IRON, Texture.DOOR_IRON_TOP), # fixme
Tile(BlockID.ORE_REDSTONE, Texture.ORE_RED_STONE), # fixme
Tile(BlockID.ORE_REDSTONE_LIT, Texture.ORE_RED_STONE), # fixme
Tile(BlockID.TOPSNOW, Texture.SNOW),
Tile(BlockID.ICE, Texture.ICE),
Tile(BlockID.SNOW, Texture.SNOW),
Tile(BlockID.CACTUS, Texture.CACTUS_SIDE),
Tile(BlockID.CLAY, Texture.CLAY),
Tile(BlockID.REEDS, Texture.REEDS),
Tile(BlockID.FENCE, Texture.PLANKS),
Tile(BlockID.INVISIBLE, Texture.STONE),
Tile(BlockID.WOOD, Texture.PLANKS),
#Tile(BlockID.LEAVES_CARRIED, Texture.LEAVES_TRANSPARENT), # fixme
Tile(BlockID.FIRE, Texture.FIRE1),
Tile(BlockID.SAPLING, Texture.SAPLING),
Tile(BlockID.SPONGE, Texture.SPONGE),
Tile(BlockID.TALL_GRASS, Texture.TALL_GRASS),
Tile(BlockID.DEAD_BUSH, Texture.DEAD_BUSH),
Tile(BlockID.PUMPKIN, Texture.PUMPKIN_FACE), # fixme
Tile(BlockID.PUMPKIN_LIT, Texture.PUMPKIN_FACE_LIT), # fixme
Tile(BlockID.NETHERRACK, Texture.BLOODSTONE),
Tile(BlockID.SOUL_SAND, Texture.SOULSAND),
Tile(BlockID.GLOWSTONE, Texture.GLOWSTONE),
Tile(BlockID.COBWEB, Texture.COBWEB),
Tile(BlockID.WORKBENCH, Texture.WORKBENCH_TOP), # fixme
Tile(BlockID.WHEAT, Texture.WHEAT_0),
# modded blocks
Tile(BlockID.YELLOW_COBBLE, Texture.YELLOW_COBBLE),
Tile(BlockID.MARBLE_YELLOW, Texture.MARBLE_YELLOW),
]
tiles_by_id = {
tile.block_id: tile for tile in tiles
}

View File

@ -1,48 +0,0 @@
# Blender 5.0.0
# www.blender.org
o Cube
v 0.250000 1.000000 -0.250000
v 0.250000 -1.000000 -0.250000
v 0.250000 1.000000 0.250000
v 0.250000 -1.000000 0.250000
v -0.250000 1.000000 -0.250000
v -0.250000 -1.000000 -0.250000
v -0.250000 1.000000 0.250000
v -0.250000 -1.000000 0.250000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 0.250000 1.250000
vt 0.500000 1.000000
vt 0.500000 1.250000
vt 0.250050 0.000100
vt 0.500000 0.999900
vt 0.250050 0.999900
vt 0.500000 0.000100
vt 0.749950 0.999900
vt 0.250000 0.000000
vt 0.500000 -0.250000
vt 0.500000 0.000000
vt 0.000100 0.000100
vt 0.000100 0.999900
vt 0.749950 0.000100
vt 0.999900 0.999900
vt 0.250000 1.000000
vt 0.250000 -0.250000
vt 0.999900 0.000100
s 0
f 5/1/1 3/2/1 1/3/1
f 3/4/2 8/5/2 4/6/2
f 7/7/3 6/8/3 8/5/3
f 2/9/4 8/10/4 6/11/4
f 1/12/5 4/6/5 2/13/5
f 5/14/6 2/15/6 6/8/6
f 5/1/1 7/16/1 3/2/1
f 3/4/2 7/7/2 8/5/2
f 7/7/3 5/14/3 6/8/3
f 2/9/4 4/17/4 8/10/4
f 1/12/5 3/4/5 4/6/5
f 5/14/6 1/18/6 2/15/6

View File

@ -3,15 +3,10 @@ import struct
from pprint import pprint
from itertools import chain
from collections import defaultdict
import functools
import os
import mcregion
import vec3
import vertex_buffer
import data
FAST = "FAST" in os.environ
def wrap_n(nc, chunk_c):
if nc < 0:
@ -22,79 +17,48 @@ def wrap_n(nc, chunk_c):
chunk_c = chunk_c + 1
return nc, chunk_c
custom_blocks = [
{ # "tallgrass" model
data.BlockID.TALL_GRASS,
data.BlockID.MUSHROOM_1,
data.BlockID.MUSHROOM_2,
data.BlockID.FLOWER,
data.BlockID.ROSE,
data.BlockID.SAPLING,
},
{ # "fence" model
data.BlockID.FENCE,
},
{ # "torch" model
data.BlockID.TORCH,
},
{ # "wheat" model
data.BlockID.WHEAT,
},
]
def block_neighbors(level_table, chunk_x, chunk_z, block_index):
block_id = level_table[(chunk_x, chunk_z)].blocks[block_index]
if block_id == 0:
return
non_solid_blocks = set(chain.from_iterable(custom_blocks))
hack_non_solid_blocks = set([
data.BlockID.LADDER,
data.BlockID.WIRE,
])
def neighbor_exists(level_table, chunk_x, chunk_z, nx, ny, nz):
def neighbor_exists(nx, ny, nz):
if ny > 127 or ny < 0:
return False
nx, n_chunk_x = wrap_n(nx, chunk_x)
nz, n_chunk_z = wrap_n(nz, chunk_z)
assert nx <= 15 and nx >= 0
assert nz <= 15 and nz >= 0
if nx > 15 or nx < 0:
return True
if nz > 15 or nz < 0:
return True
n_block_index = mcregion.block_index_from_xyz(nx, ny, nz)
key = (n_chunk_x, n_chunk_z)
if key not in level_table:
return True
n_block_index = mcregion.block_index_from_xyz(nx, ny, nz)
n_block_id = level_table[key].blocks[n_block_index]
return n_block_id != 0
has_neighbor = (n_block_id != data.BlockID.AIR) and (n_block_id not in non_solid_blocks) and (n_block_id not in hack_non_solid_blocks)
return has_neighbor
x, y, z = mcregion.xyz_from_block_index(block_index)
def block_neighbors(level_table, chunk_x, chunk_z, block_index):
block_id = level_table[(chunk_x, chunk_z)].blocks[block_index]
if block_id == data.BlockID.AIR:
return
block_data = level_table[(chunk_x, chunk_z)].data[block_index // 2]
block_data = (block_data >> (1 - (block_index % 2)) * 4) & 0xf
xyz = mcregion.xyz_from_block_index(block_index)
center_position = vec3.add(xyz, (chunk_x * 16, 0, chunk_z * 16))
center_position = vec3.add((x, y, z), (chunk_x * 16, 0, chunk_z * 16))
def find_non_neighbors():
for i, normal in enumerate(vertex_buffer.normals):
neighbor = vec3.add(normal, xyz)
if not neighbor_exists(level_table, chunk_x, chunk_z, *neighbor):
neighbor = vec3.add(normal, (x, y, z))
if not neighbor_exists(*neighbor):
yield i
normal_indices = list(find_non_neighbors())
if block_id in non_solid_blocks or block_id in hack_non_solid_blocks or normal_indices:
yield center_position, block_id, block_data, normal_indices
if normal_indices:
yield center_position, block_id, normal_indices
def devoxelize_region(level_table, level_table_keys):
for chunk_x, chunk_z in level_table_keys:
def devoxelize_region(level_table):
for chunk_x, chunk_z in level_table.keys():
for block_index in range(128 * 16 * 16):
yield from block_neighbors(level_table, chunk_x, chunk_z, block_index)
if FAST:
return
def build_level_table(level_table, mem, locations):
def build_level_table(mem, locations):
level_table = {}
for location in locations:
try:
level = mcregion.parse_location(mem, location)
@ -118,84 +82,38 @@ def build_block_configuration_table():
indices.extend(vertex_buffer.faces_by_normal[vertex_buffer.normals[j]])
yield indices
def pack_instance_data(position, block_id, block_data):
packed = struct.pack("<hhhBB",
position[0], position[1], position[2],
block_id,
block_data)
return packed
def pack_light_data(position, block_id):
packed = struct.pack("<ffff", position[0], position[1], position[2], block_id)
return packed
def build_block_instances(blocks):
by_configuration = defaultdict(list)
deferred_blocks = defaultdict(list)
light_sources = []
def is_deferred_block(position, block_id, block_data):
for i, custom_block_types in enumerate(custom_blocks):
if block_id in custom_block_types:
deferred_blocks[i].append((position, block_id, block_data))
return True
return False
for position, block_id, block_data, normal_indices in blocks:
if block_id == data.BlockID.TORCH:
light_sources.append((position, block_id))
if is_deferred_block(position, block_id, block_data):
assert block_id in non_solid_blocks
continue
for position, block_id, normal_indices in blocks:
configuration = normal_indices_as_block_configuration(normal_indices)
by_configuration[configuration].append((position, block_id, block_data))
#print(position, block_id, block_configuration)
by_configuration[configuration].append((position, block_id))
offset = 0
configuration_instance_count_offset = []
with open(f"{data_path}.instance.vtx", "wb") as f:
######################################################################
# cubes
######################################################################
for configuration in range(64):
if configuration not in by_configuration:
configuration_instance_count_offset.append((0, 0))
continue
_blocks = by_configuration[configuration]
configuration_instance_count_offset.append((len(_blocks), offset))
for position, block_id, block_data in _blocks:
assert block_id not in non_solid_blocks, block_id
packed = pack_instance_data(position, block_id, block_data)
blocks = by_configuration[configuration]
configuration_instance_count_offset.append((len(blocks), offset))
for position, block_id in blocks:
packed = struct.pack("<hhhBB",
position[0], position[1], position[2],
block_id,
0)
f.write(packed)
offset += len(packed)
######################################################################
# non-cubes
######################################################################
for custom_block_ix in range(len(custom_blocks)):
nc_offset = offset
nc_instance_count = 0
for position, block_id, block_data in deferred_blocks[custom_block_ix]:
assert block_id in non_solid_blocks, block_id
packed = pack_instance_data(position, block_id, block_data)
f.write(packed)
offset += len(packed)
nc_instance_count += 1
configuration_instance_count_offset.append((nc_instance_count, nc_offset))
with open(f"{data_path}.instance.cfg", "wb") as f:
for instance_count, offset in configuration_instance_count_offset:
#print(instance_count, offset)
print(instance_count, offset)
f.write(struct.pack("<ii", instance_count, offset))
with open(f"{data_path}.lights.vtx", "wb") as f:
for position, block_id in light_sources:
packed = pack_light_data(position, block_id)
f.write(packed)
def level_table_from_path(level_table, path):
with open(path, "rb") as f:
def main(mcr_path, data_path):
with open(mcr_path, "rb") as f:
buf = f.read()
mem = memoryview(buf)
@ -204,34 +122,13 @@ def level_table_from_path(level_table, path):
offset, timestamps = mcregion.parse_timestamps(mem, offset)
assert offset == 0x2000
build_level_table(level_table, mem, locations)
all_paths = [
"/home/bilbo/Love2DWorld/region/r.0.0.mcr",
"/home/bilbo/Love2DWorld/region/r.-1.-1.mcr",
"/home/bilbo/Love2DWorld/region/r.0.-1.mcr",
"/home/bilbo/Love2DWorld/region/r.-1.0.mcr",
]
def main2(level_table, level_table_keys):
blocks = devoxelize_region(level_table, level_table_keys)
level_table = build_level_table(mem, locations)
blocks = devoxelize_region(level_table)
build_block_instances(blocks)
def main(mcr_path, data_path):
assert mcr_path in all_paths
level_table = {}
level_table_from_path(level_table, mcr_path)
level_table_keys = list(level_table.keys())
for path in all_paths:
if path == mcr_path:
continue
level_table_from_path(level_table, path)
main2(level_table, level_table_keys)
#import cProfile
#cProfile.runctx("main2(level_table, level_table_keys)", {},
# {"level_table_keys": level_table_keys, "level_table": level_table, "main2": main2})
#pprint(list(build_block_configuration_table()))
mcr_path = sys.argv[1]
data_path = sys.argv[2]
main(mcr_path, data_path)

View File

@ -1,11 +0,0 @@
set -eux
cd ./minecraft/gen
PYTHON=pypy3.11
$PYTHON mc.py ~/Love2DWorld/region/r.0.0.mcr ../region.0.0 &
$PYTHON mc.py ~/Love2DWorld/region/r.-1.-1.mcr ../region.-1.-1 &
$PYTHON mc.py ~/Love2DWorld/region/r.0.-1.mcr ../region.0.-1 &
$PYTHON mc.py ~/Love2DWorld/region/r.-1.0.mcr ../region.-1.0 &
wait
cat ../region*.lights.vtx > ../global.lights.vtx

View File

@ -217,30 +217,15 @@ def parse_location(mem, location):
level = level_from_tag(tag)
return level
def _xyz_from_block_index(block_index):
def xyz_from_block_index(block_index):
assert block_index >= 0 and block_index < (128 * 16 * 16)
x = block_index // (128 * 16)
y = block_index % 128
z = (block_index // 128) % 16
x = int(block_index / (128 * 16))
y = int(block_index % 128)
z = int(int(block_index / 128) % 16)
return x, y, z
def _block_index_from_xyz(x, y, z):
def block_index_from_xyz(x, y, z):
assert x >= 0 and x < 16
assert y >= 0 and y < 128
assert z >= 0 and z < 16
return int(y + z * 128 + x * 128 * 16)
xyz_to_block_index = {}
block_index_to_xyz = {}
for i in range(128 * 16 * 16):
xyz = _xyz_from_block_index(i)
assert _block_index_from_xyz(*xyz) == i
xyz_to_block_index[xyz] = i
block_index_to_xyz[i] = xyz
def xyz_from_block_index(block_index):
return block_index_to_xyz[block_index]
def block_index_from_xyz(x, y, z):
return xyz_to_block_index[(x, y, z)]

View File

@ -1,150 +0,0 @@
import struct
from collections import defaultdict
import sys
import data
files = sys.argv[1:]
by_block_id = defaultdict(list)
no_tile = defaultdict(list)
block_ids = {
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
}
for filename in files:
with open(filename, 'rb') as f:
buf = f.read()
for i in range(len(buf) // 8):
x, y, z, block_id, block_data = struct.unpack("<hhhBB", buf[i*8:i*8+8])
if block_id == 35:
print(x, y, z, block_data)
if block_id not in block_ids and block_id not in data.tiles_by_id:
by_block_id[block_id].append((x, y, z, block_data))
elif block_id not in data.tiles_by_id:
no_tile[block_id].append((x, y, z, block_data))
print("no block id:")
for key in sorted(by_block_id.keys()):
print(" ", key, len(by_block_id[key]), by_block_id[key][0])
print("no tile:")
for key in sorted(no_tile.keys()):
print(" ", key, len(no_tile[key]), no_tile[key][0])

View File

@ -1,80 +0,0 @@
from dataclasses import dataclass
def ignore(state, line):
pass
def normalize_float(s):
f = float(s)
if f == -0.0:
return 0.0
return f
def parse_float_components(s, length):
components = s.split()
assert len(components) == length
return tuple(map(normalize_float, components))
def parse_position(state, line):
position = parse_float_components(line, 3)
state.position.append(position)
def parse_normal(state, line):
normal = parse_float_components(line, 3)
state.normal.append(normal)
def parse_texture(state, line):
texture = parse_float_components(line, 2)
state.texture.append(texture)
def parse_ptn(s):
ptn = tuple(int(i) - 1 for i in s.split("/"))
assert all(c >= 0 for c in ptn), ptn
assert len(ptn) == 3, ptn
return ptn
def parse_triangle(state, line):
indices = line.split()
assert len(indices) == 3, line
triangle = tuple(map(parse_ptn, indices))
state.triangle.append(triangle)
prefixes = [
("#", ignore),
("o ", ignore),
("s ", ignore),
("v ", parse_position),
("vn ", parse_normal),
("vt ", parse_texture),
("f ", parse_triangle),
]
@dataclass
class ObjState:
position: list
normal: list
texture: list
triangle: list
def __init__(self):
self.position = []
self.normal = []
self.texture = []
self.triangle = []
def parse_obj(s):
state = ObjState()
lines = s.strip().split("\n")
for line in lines:
for prefix, func in prefixes:
if line.startswith(prefix):
line = line.removeprefix(prefix)
func(state, line)
break
else:
assert False, line
return state
def parse_obj_from_filename(filename):
with open(filename, "r") as f:
buf = f.read()
return parse_obj(buf)

View File

@ -1,25 +0,0 @@
from collections import defaultdict
import obj
def append_triangles(state, vertex_buffer, index_buffer, index_lookup):
for triangle in state.triangle:
for p_ix, t_ix, n_ix in triangle:
key = (p_ix, n_ix, t_ix)
if key not in index_lookup:
position = state.position[p_ix]
normal = state.normal[n_ix]
texture = state.texture[t_ix]
index = len(vertex_buffer)
index_lookup[key] = index
vertex_buffer.append((position, normal, texture))
index_buffer.append(index_lookup[key])
def build_faces_by_normal(vertex_buffer, index_buffer):
by_normal = defaultdict(list)
for i in range(len(index_buffer) // 3):
tri = [index_buffer[i * 3 + n] for n in range(3)]
s = set(vertex_buffer[j][1] for j in tri)
assert len(s) == 1, s
normal, = iter(s)
by_normal[normal].extend(tri)
return by_normal

View File

@ -1,24 +0,0 @@
# Blender 5.0.0
# www.blender.org
o TallGrass
v 0.800000 0.600000 0.800000
v 0.800000 -1.000000 0.800000
v -0.800000 -1.000000 0.800000
v -0.800000 0.600000 0.800000
v -0.800000 0.600000 -0.800000
v -0.800000 -1.000000 -0.800000
v 0.800000 -1.000000 -0.800000
v 0.800000 0.600000 -0.800000
vn 0.7071 -0.0000 0.7071
vn 0.7071 -0.0000 -0.7071
vt 1.000000 1.000000
vt 0.000000 -0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt -0.000000 1.000000
vt 1.000000 0.000000
s 0
f 3/1/1 8/2/1 4/3/1
f 5/2/2 2/4/2 6/5/2
f 3/1/1 7/5/1 8/2/1
f 5/2/2 1/6/2 2/4/2

View File

@ -1,40 +0,0 @@
# Blender 5.0.0
# www.blender.org
o Cube
v 0.125000 0.250000 -0.125000
v 0.125000 -1.000000 -0.125000
v 0.125000 0.250000 0.125000
v 0.125000 -1.000000 0.125000
v -0.125000 0.250000 -0.125000
v -0.125000 -1.000000 -0.125000
v -0.125000 0.250000 0.125000
v -0.125000 -1.000000 0.125000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 0.531250 0.406250
vt 0.468750 0.468750
vt 0.468750 0.406250
vt 0.437500 0.375000
vt 0.562500 1.000000
vt 0.437500 1.000000
vt 0.562500 0.875000
vt 0.437500 0.875000
vt 0.531250 0.468750
vt 0.562500 0.375000
s 0
f 5/1/1 3/2/1 1/3/1
f 3/4/2 8/5/2 4/6/2
f 7/4/3 6/5/3 8/6/3
f 2/7/4 8/6/4 6/8/4
f 1/4/5 4/5/5 2/6/5
f 5/4/6 2/5/6 6/6/6
f 5/1/1 7/9/1 3/2/1
f 3/4/2 7/10/2 8/5/2
f 7/4/3 5/10/3 6/5/3
f 2/7/4 4/5/4 8/6/4
f 1/4/5 3/10/5 4/5/5
f 5/4/6 1/10/6 2/5/6

View File

@ -1,8 +1,41 @@
import struct
import vec3
import obj
import obj_state
import sys
vertex_table = [
((-1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (1.0, 0.0)),
((1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (0.0, 1.0)),
((1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (0.0, 0.0)),
((1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 1.0)),
((-1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0)),
((1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 0.0)),
((-1.0, 1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 1.0)),
((-1.0, -1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 0.0)),
((-1.0, -1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 0.0)),
((1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (1.0, 0.0)),
((-1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (0.0, 1.0)),
((-1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (0.0, 0.0)),
((1.0, 1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 1.0)),
((1.0, -1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 0.0)),
((1.0, -1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 0.0)),
((-1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 1.0)),
((1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 0.0)),
((-1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 0.0)),
((-1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (1.0, 1.0)),
((-1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 1.0)),
((-1.0, 1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 1.0)),
((1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (1.0, 1.0)),
((1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0)),
((1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 1.0))
]
faces_by_normal = {
(-1.0, 0.0, 0.0): [6, 7, 8, 6, 20, 7],
(0.0, -1.0, 0.0): [9, 10, 11, 9, 21, 10],
(0.0, 0.0, -1.0): [15, 16, 17, 15, 23, 16],
(0.0, 0.0, 1.0): [3, 4, 5, 3, 19, 4],
(0.0, 1.0, 0.0): [0, 1, 2, 0, 18, 1],
(1.0, 0.0, 0.0): [12, 13, 14, 12, 22, 13]
}
normals = [
(-1.0, 0.0, 0.0),
@ -13,9 +46,7 @@ normals = [
(1.0, 0.0, 0.0),
]
def build_configuration_index_buffers(f, faces_by_normal, index_buffer):
assert(set(normals) == set(faces_by_normal.keys()))
def build_configuration_index_buffers(f):
offset = 0
configuration_offsets = []
for configuration in range(64):
@ -27,7 +58,6 @@ def build_configuration_index_buffers(f, faces_by_normal, index_buffer):
indices = faces_by_normal[normal]
for index in indices:
f.write(struct.pack("<B", index))
index_buffer.append(index)
offset += 1
for i, offset in enumerate(configuration_offsets):
@ -35,49 +65,14 @@ def build_configuration_index_buffers(f, faces_by_normal, index_buffer):
if i % 8 == 7:
print()
def build_vertex_buffer(f, vertex_buffer):
for position, normal, texture in vertex_buffer:
def build_vertex_buffer(f):
for position, normal, texture in vertex_table:
position = vec3.mul(position, 0.5)
f.write(struct.pack("<eeeeeeee", *position, *normal, *texture))
def write_indices(f, index_buffer, start, count):
for i in range(count):
f.write(struct.pack("<B", index_buffer[start + i]))
def write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, path):
index_start = len(index_buffer)
state = obj.parse_obj_from_filename(path)
obj_state.append_triangles(state, vertex_buffer, index_buffer, index_lookup)
index_count = len(index_buffer) - index_start
write_indices(f, index_buffer, index_start, index_count)
print(f"{index_start}, {index_count}, // {path}")
def main():
cube_index_buffer = []
cube_index_lookup = {}
vertex_buffer = []
index_buffer = []
index_lookup = {}
cube_state = obj.parse_obj_from_filename("cube.obj")
obj_state.append_triangles(cube_state, vertex_buffer, cube_index_buffer, cube_index_lookup)
cube_faces_by_normal = obj_state.build_faces_by_normal(vertex_buffer, cube_index_buffer)
with open("../configuration.idx", "wb") as f:
build_configuration_index_buffers(f, cube_faces_by_normal, index_buffer)
index_lookup = {}
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "tallgrass.obj")
index_lookup = {}
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "fence.obj")
index_lookup = {}
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "torch.obj")
index_lookup = {}
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "wheat.obj")
with open("../per_vertex.vtx", "wb") as f:
build_vertex_buffer(f, vertex_buffer)
if __name__ == "__main__":
main()
with open("configuration.idx", "wb") as f:
build_configuration_index_buffers(f)
with open("per_vertex.vtx", "wb") as f:
build_vertex_buffer(f)

View File

@ -1,36 +0,0 @@
# Blender 5.0.0
# www.blender.org
o Cube
v -0.500000 -1.000000 -1.000000
v -0.500000 1.000000 -1.000000
v 1.000000 -1.000000 0.500000
v 1.000000 1.000000 0.500000
v 0.500000 1.000000 -1.000000
v 0.500000 -1.000000 -1.000000
v 0.500000 1.000000 1.000000
v 0.500000 -1.000000 1.000000
v 1.000000 1.000000 -0.500000
v 1.000000 -1.000000 -0.500000
v -1.000000 1.000000 -0.500000
v -1.000000 -1.000000 -0.500000
v -0.500000 1.000000 1.000000
v -0.500000 -1.000000 1.000000
v -1.000000 1.000000 0.500000
v -1.000000 -1.000000 0.500000
vn -0.0000 -0.0000 1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -1.0000 -0.0000 -0.0000
vt 0.000000 -0.000000
vt 1.000000 1.000000
vt -0.000000 1.000000
vt 1.000000 0.000000
s 0
f 4/1/1 16/2/1 3/3/1
f 5/1/2 8/2/2 6/3/2
f 11/1/3 10/2/3 12/3/3
f 13/1/4 1/2/4 14/3/4
f 4/1/1 15/4/1 16/2/1
f 5/1/2 7/4/2 8/2/2
f 11/1/3 9/4/3 10/2/3
f 13/1/4 2/4/4 1/2/4

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -1,18 +0,0 @@
#version 330 core
uniform sampler2D TextureSampler;
uniform vec2 Cell;
uniform vec2 Glyph;
out vec4 g_color;
in vec4 PixelTexture;
void main()
{
vec4 sample = texture(TextureSampler, PixelTexture.xy * Cell + Cell * Glyph);
float px = sample.x == 0.0 ? 0.0 : 1.0;
g_color = vec4(vec3(px), 1.0);
}

View File

@ -1,39 +0,0 @@
#version 330 core
const vec2 vtx[4] = vec2[](vec2(-1.0, 1.0), // tl
vec2( 1.0, 1.0), // tr
vec2( 1.0, -1.0), // br
vec2(-1.0, -1.0)); // bl
/*
tl tr
br
0 1 2
tr tl br
1 0 2
tl
bl br
2 1 3
br tl bl
2 0 3
1 0 2 3
*/
uniform mat4 Transform;
out vec4 PixelTexture;
void main()
{
vec2 vertex = vtx[gl_VertexID];
PixelTexture = vec4(vertex * vec2(0.5, -0.5) + 0.5, 0, 0);
vertex = vertex * vec2(0.5, 0.5) + vec2(0.5, -0.5);
gl_Position = Transform * vec4(vertex, 0.0, 1.0);
}

View File

@ -1,40 +0,0 @@
#version 330 core
uniform sampler2D PositionSampler;
uniform sampler2D NormalSampler;
uniform sampler2D ColorSampler;
uniform float Linear;
uniform float Quadratic;
uniform vec3 Eye;
layout (location = 0) out vec4 Color;
in vec4 PixelTexture;
layout (std140) uniform Lights
{
vec4 light[256];
};
void main()
{
vec4 position = texture(PositionSampler, PixelTexture.xy);
vec4 normal = texture(NormalSampler, PixelTexture.xy);
vec4 color = texture(ColorSampler, PixelTexture.xy);
vec3 out_color = color.xyz * 0.1;
for (int i = 0; i < 82; i++) {
vec3 light_position = light[i].xzy;
float light_distance = length(light_position - position.xyz);
vec3 light_direction = normalize(light_position - position.xyz);
float diffuse = max(dot(normal.xyz, light_direction), 0.0);
//float attenuation = 1.0 / (1.0 + Linear * light_distance + Quadratic * light_distance * light_distance);
float attenuation = 1.0 / (1.0 + Quadratic * light_distance * light_distance);
out_color += color.xyz * attenuation * diffuse;
//out_color = vec3(diffuse);
}
Color = vec4(out_color, 1.0);
}

View File

@ -1,13 +0,0 @@
#version 330 core
uniform sampler2D TextureSampler;
layout (location = 0) out vec4 Color;
in vec4 PixelTexture;
void main()
{
vec4 sample = texture(TextureSampler, PixelTexture.xy);
Color = vec4(sample.xyz, 1.0);
}

View File

@ -1,17 +0,0 @@
#version 330 core
const vec2 vtx[4] = vec2[](vec2(-1.0, 1.0), // tl
vec2( 1.0, 1.0), // tr
vec2( 1.0, -1.0), // br
vec2(-1.0, -1.0)); // bl
out vec4 PixelTexture;
void main()
{
vec2 vertex = vtx[gl_VertexID];
PixelTexture = vec4(vertex * 0.5 + 0.5, 0, 0);
gl_Position = vec4(vertex, 0.0, 1.0);
}

View File

@ -1,50 +1,40 @@
#version 330 core
in VS_OUT {
vec3 Position; // world coordinates
vec3 Normal;
vec2 Texture;
flat int BlockID;
flat int Data;
} fs_in;
layout (location = 0) out vec3 Position;
layout (location = 1) out vec3 Normal;
layout (location = 2) out vec3 Color;
out vec4 FragColor;
uniform sampler2D TerrainSampler;
layout (std140) uniform TextureID
{
ivec4 block_id_to_texture_id[256 / 4];
};
int wool[16] = int[16]( 64, // 0 64
210, // 32 208
194, // 32 192
178, // 32 176
162, // 32 160
146, // 32 144
130, // 32 128
114, // 32 112
225, // 16 224
209, // 16 208
193, // 16 192
177, // 16 176
161, // 16 160
145, // 16 144
129, // 16 128
113 // 16 112
);
int Textures[256] = int[256](
185, 1, 0, 2, 16, 4, 15, 17, 205, 205, 237, 237, 18, 19, 32, 33,
34, 20, 52, 48, 49, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 0,
185, 185, 185, 64, 185, 13, 12, 29, 28, 39, 38, 5, 5, 7, 8, 35,
36, 37, 80, 31, 65, 4, 27, 84, 50, 40, 43, 88, 87, 44, 61, 185,
81, 83, 128, 16, 185, 96, 6, 82, 6, 51, 51, 115, 99, 185, 66, 67,
66, 70, 72, 73, 74, 4, 102, 103, 104, 105, 14, 102, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185
);
void main()
{
int terrain_ix;
if (fs_in.BlockID == 35) // cloth
terrain_ix = wool[fs_in.Data];
else
terrain_ix = block_id_to_texture_id[fs_in.BlockID / 4][fs_in.BlockID % 4];
vec3 light_direction = normalize(vec3(-1, -0.5, 0.5));
float diffuse_intensity = max(dot(normalize(fs_in.Normal), light_direction), 0.0);
int terrain_ix = int(Textures[int(fs_in.BlockID)]);
int terrain_x = terrain_ix % 16;
int terrain_y = terrain_ix / 16;
ivec2 coord = ivec2(terrain_x, terrain_y) * 16;
@ -56,10 +46,11 @@ void main()
return;
}
if (fs_in.BlockID == 18 || fs_in.BlockID == 31) // leaves
if (int(fs_in.BlockID) == 18) // leaves
texture_color.xyz *= vec3(0.125, 0.494, 0.027);
Position = fs_in.Position.xzy;
Normal = normalize(fs_in.Normal.xzy);
Color = texture_color.xyz;
if (diffuse_intensity < 0.1)
diffuse_intensity = 0.1;
FragColor = vec4(texture_color.xyz * vec3(diffuse_intensity), 1.0);
}

View File

@ -7,27 +7,20 @@ in vec2 Texture;
// per-instance:
in vec3 BlockPosition;
in float BlockID;
in float Data;
out VS_OUT {
vec3 Position;
vec3 Normal;
vec2 Texture;
flat int BlockID;
flat int Data;
} vs_out;
uniform mat4 Transform;
void main()
{
vec3 position = Position + BlockPosition; // world coordinates
vs_out.Position = position;
vs_out.Normal = Normal;
vs_out.Normal = Normal.xzy;
vs_out.Texture = Texture;
vs_out.BlockID = int(BlockID);
vs_out.Data = int(Data);
gl_Position = Transform * vec4(position.xzy, 1.0);
gl_Position = Transform * vec4((Position + BlockPosition).xzy, 1.0);
}

View File

@ -1,167 +0,0 @@
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "directxmath/directxmath.h"
#include "glad/gl.h"
#include "opengl.h"
#include "font.h"
#include "window.h"
namespace font {
struct location {
struct {
unsigned int transform;
unsigned int texture_sampler;
unsigned int cell;
unsigned int glyph;
} uniform;
};
static location location;
static unsigned int font_program = -1;
void load_shader()
{
unsigned int program = compile_from_files("shader/font.vert",
NULL, // geom
"shader/font.frag");
location.uniform.transform = glGetUniformLocation(program, "Transform");
location.uniform.texture_sampler = glGetUniformLocation(program, "TextureSampler");
location.uniform.cell = glGetUniformLocation(program, "Cell");
location.uniform.glyph = glGetUniformLocation(program, "Glyph");
printf("font program:\n");
printf(" uniforms:\n transform %u\n texture_sampler %u\n cell %u\n glyph %u\n",
location.uniform.transform,
location.uniform.texture_sampler,
location.uniform.cell,
location.uniform.glyph
);
font_program = program;
}
font load_font(font_desc const& desc)
{
unsigned int texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int texture_data_size;
void * texture_data = read_file(desc.path, &texture_data_size);
assert(texture_data != nullptr);
int width = desc.texture_width;
int height = desc.texture_height;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, texture_data);
free(texture_data);
glBindTexture(GL_TEXTURE_2D, 0);
return (font){
.desc = &desc,
.texture = texture,
.stride = desc.texture_width / desc.glyph_width,
.cell = { (float)desc.glyph_width / (float)desc.texture_width,
(float)desc.glyph_height / (float)desc.texture_height },
};
}
static inline int min(int a, int b)
{
return a < b ? a : b;
}
int best_font(font_desc const * const descs, int length)
{
int dimension = min(g_window_width, g_window_height);
int ideal_height = (16 * dimension) / 1024;
//printf("ideal_height: %d\n", ideal_height);
int nearest = dimension;
int nearest_ix = -1;
for (int i = 0; i < length; i++) {
font_desc const& desc = descs[i];
int distance = abs(desc.glyph_height - ideal_height);
if (distance < nearest) {
nearest = distance;
nearest_ix = i;
}
}
assert(nearest_ix != -1);
//printf("selected %d\n", descs[nearest_ix].glyph_height);
return nearest_ix;
}
void load_fonts(font * const fonts, font_desc const * const descs, int length)
{
for (int i = 0; i < length; i++) {
fonts[i] = load_font(descs[i]);
}
}
inline static XMFLOAT2 glyph_coordinate(font const& font, int ord)
{
int c = ord - 32;
int x = c % font.stride;
int y = c / font.stride;
XMVECTOR coord = XMVectorSet(x, y, 0, 0);
XMFLOAT2 coordf;
XMStoreFloat2(&coordf, coord);
return coordf;
}
inline static XMFLOAT4X4 glyph_transform(font const& font, int x, int y)
{
XMMATRIX transform =
XMMatrixScaling(font.desc->glyph_width, font.desc->glyph_height, 0)
* XMMatrixTranslation(x, -y, 0)
* XMMatrixScaling(2.0f / g_window_width, 2.0f / g_window_height, 0)
* XMMatrixTranslation(-1, 1, 0);
XMFLOAT4X4 transformf;
XMStoreFloat4x4(&transformf, transform);
return transformf;
}
void draw_start(font const& font, unsigned int vertex_array_object, unsigned int index_buffer)
{
glUseProgram(font_program);
glDepthFunc(GL_ALWAYS);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, font.texture);
glUniform1i(location.uniform.texture_sampler, 0);
glUniform2fv(location.uniform.cell, 1, (float *)&font.cell);
glBindVertexArray(vertex_array_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
}
void draw_string(font const& font, char const * const s, int x, int y)
{
int i = 0;
while (s[i] != 0) {
char c = s[i++];
if (!(c <= 0x20 || c > 0x7f)) {
XMFLOAT4X4 transform = glyph_transform(font, x, y);
glUniformMatrix4fv(location.uniform.transform, 1, GL_FALSE, (float *)&transform);
XMFLOAT2 glyph = glyph_coordinate(font, c);
glUniform2fv(location.uniform.glyph, 1, (float *)&glyph);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
}
x += font.desc->glyph_width;
}
}
}

View File

@ -7,30 +7,8 @@
#include "glad/gl.h"
#include "opengl.h"
char const * g_source_path = NULL;
int g_source_path_length = 0;
char const * join_path(char * buf, const char * filename)
void * read_file(const char * filename, int * out_size)
{
if (filename[0] == '/')
return filename;
int filename_length = strlen(filename);
assert(filename_length + g_source_path_length + 2 < 1024);
memcpy(buf, g_source_path, g_source_path_length);
buf[g_source_path_length] = '/';
memcpy(&buf[g_source_path_length + 1], filename, filename_length);
buf[g_source_path_length + 1 + filename_length] = 0;
return buf;
}
void * read_file(const char * r_filename, int * out_size)
{
char tmp[1024];
char const * filename = join_path(tmp, r_filename);
FILE * f = fopen(filename, "rb");
if (f == NULL) {
fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno));

View File

@ -6,58 +6,27 @@
#include "opengl.h"
#include "directxmath/directxmath.h"
#include "test.h"
#include "font.h"
#include "window.h"
#include "data.inc"
struct test_location {
struct location {
struct {
unsigned int position;
unsigned int normal;
unsigned int texture;
unsigned int block_position;
unsigned int block_id;
unsigned int data;
//unsigned int configuration;
} attrib;
struct {
unsigned int transform;
unsigned int terrain_sampler;
unsigned int texture_id;
} uniform;
struct {
unsigned int texture_id;
} binding;
};
// state
static unsigned int test_program;
static test_location test_location;
struct quad_location {
struct {
unsigned int texture_sampler;
} uniform;
};
static unsigned int quad_program;
static quad_location quad_location;
struct lighting_location {
struct {
unsigned int position_sampler;
unsigned int normal_sampler;
unsigned int color_sampler;
unsigned int quadratic;
unsigned int linear;
unsigned int eye;
unsigned int lights;
} uniform;
struct {
unsigned int lights;
} binding;
};
static unsigned int lighting_program;
static lighting_location lighting_location;
static struct location location;
struct char_tpl {
const char * vtx;
@ -65,147 +34,73 @@ struct char_tpl {
};
static const int region_count = 4;
static const char_tpl vertex_paths[] = {
static const char_tpl vertex_paths[region_count] = {
{ "minecraft/region.0.0.instance.vtx", "minecraft/region.0.0.instance.cfg" },
{ "minecraft/region.-1.0.instance.vtx", "minecraft/region.-1.0.instance.cfg" },
{ "minecraft/region.0.-1.instance.vtx", "minecraft/region.0.-1.instance.cfg" },
{ "minecraft/region.-1.-1.instance.vtx", "minecraft/region.-1.-1.instance.cfg" },
};
static unsigned int vertex_array_object;
static unsigned int per_instance_vertex_buffers[region_count];
static unsigned int vertex_array_objects[region_count];
static unsigned int vertex_buffers[region_count];
static unsigned int vertex_count[region_count];
static unsigned int index_buffer;
static unsigned int per_vertex_buffer;
static const int vertex_size = 8;
static const int per_vertex_size = (3 + 3 + 2) * 2;
// also update index_buffer_custom_offsets in data.inc
static const int custom_block_types = 4;
static const int instance_cfg_length = 64 + custom_block_types;
struct instance_cfg {
struct region_instance {
struct {
int instance_count;
int offset;
} cfg[instance_cfg_length];
} cfg[64];
};
static instance_cfg instance_cfg[region_count];
static unsigned int empty_vertex_array_object = -1;
static unsigned int quad_index_buffer = -1;
void load_quad_index_buffer()
{
uint8_t const data[] = {
1, 0, 2, 3,
};
int const data_size = (sizeof (data));
glGenBuffers(1, &quad_index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size, data, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &empty_vertex_array_object);
}
void load_test_program()
void load_program()
{
unsigned int program = compile_from_files("shader/test.vert",
NULL,
NULL, //"shader/test.geom",
"shader/test.frag");
test_location.attrib.position = glGetAttribLocation(program, "Position");
test_location.attrib.normal = glGetAttribLocation(program, "Normal");
test_location.attrib.texture = glGetAttribLocation(program, "Texture");
location.attrib.position = glGetAttribLocation(program, "Position");
location.attrib.normal = glGetAttribLocation(program, "Normal");
location.attrib.texture = glGetAttribLocation(program, "Texture");
test_location.attrib.block_position = glGetAttribLocation(program, "BlockPosition");
test_location.attrib.block_id = glGetAttribLocation(program, "BlockID");
test_location.attrib.data = glGetAttribLocation(program, "Data");
printf("test program:\n");
printf(" attributes:\n position %u\n normal %u\n texture %u\n block_position %u\n block_id %u\n block_id %u\n",
test_location.attrib.position,
test_location.attrib.normal,
test_location.attrib.texture,
test_location.attrib.block_position,
test_location.attrib.block_id,
test_location.attrib.data);
location.attrib.block_position = glGetAttribLocation(program, "BlockPosition");
location.attrib.block_id = glGetAttribLocation(program, "BlockID");
printf("attributes:\n position %u\n normal %u\n texture %u\n block_position %u\n block_id %u\n\n",
location.attrib.position,
location.attrib.normal,
location.attrib.texture,
location.attrib.block_position,
location.attrib.block_id);
test_location.uniform.transform = glGetUniformLocation(program, "Transform");
test_location.uniform.terrain_sampler = glGetUniformLocation(program, "TerrainSampler");
test_location.uniform.texture_id = glGetUniformBlockIndex(program, "TextureID");
printf(" uniforms:\n transform %u\n terrain_sampler %u\n texture_id %u\n",
test_location.uniform.transform,
test_location.uniform.terrain_sampler,
test_location.uniform.texture_id);
test_location.binding.texture_id = 0;
glUniformBlockBinding(program, test_location.uniform.texture_id, test_location.binding.texture_id);
location.uniform.transform = glGetUniformLocation(program, "Transform");
location.uniform.terrain_sampler = glGetUniformLocation(program, "TerrainSampler");
printf("uniforms:\n transform %u\n terrain_sampler %u\n",
location.uniform.transform,
location.uniform.terrain_sampler);
test_program = program;
}
void load_quad_program()
{
unsigned int program = compile_from_files("shader/quad.vert",
NULL,
"shader/quad.frag");
quad_location.uniform.texture_sampler = glGetUniformLocation(program, "TextureSampler");
printf("quad program:\n");
printf(" uniforms:\n texture_sampler %u\n",
quad_location.uniform.texture_sampler);
quad_program = program;
}
void load_lighting_program()
{
unsigned int program = compile_from_files("shader/quad.vert",
NULL,
"shader/lighting.frag");
lighting_location.uniform.position_sampler = glGetUniformLocation(program, "PositionSampler");
lighting_location.uniform.normal_sampler = glGetUniformLocation(program, "NormalSampler");
lighting_location.uniform.color_sampler = glGetUniformLocation(program, "ColorSampler");
lighting_location.uniform.quadratic = glGetUniformLocation(program, "Quadratic");
lighting_location.uniform.linear = glGetUniformLocation(program, "Linear");
lighting_location.uniform.eye = glGetUniformLocation(program, "Eye");
lighting_location.uniform.lights = glGetUniformBlockIndex(program, "Lights");
fprintf(stderr, "lighting program:\n");
fprintf(stderr, " uniforms:\n position_sampler %u normal_sampler %u color_sampler %u lights %u\n",
lighting_location.uniform.position_sampler,
lighting_location.uniform.normal_sampler,
lighting_location.uniform.color_sampler,
lighting_location.uniform.lights);
lighting_location.binding.lights = 0;
glUniformBlockBinding(program, lighting_location.uniform.lights, lighting_location.binding.lights);
lighting_program = program;
}
void load_per_instance_vertex_buffer(int i)
void load_vertex_buffer(int i)
{
int vertex_buffer_data_size;
void * vertex_buffer_data = read_file(vertex_paths[i].vtx, &vertex_buffer_data_size);
glBindBuffer(GL_ARRAY_BUFFER, per_instance_vertex_buffers[i]);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers[i]);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW);
vertex_count[i] = vertex_buffer_data_size / vertex_size;
free(vertex_buffer_data);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void load_per_vertex_buffer()
{
glGenBuffers(1, &per_vertex_buffer);
int vertex_buffer_data_size;
void * vertex_buffer_data = read_file("minecraft/per_vertex.vtx", &vertex_buffer_data_size);
@ -213,14 +108,10 @@ void load_per_vertex_buffer()
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW);
free(vertex_buffer_data);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void load_index_buffer()
{
glGenBuffers(1, &index_buffer);
int index_buffer_data_size;
void * index_buffer_data = read_file("minecraft/configuration.idx", &index_buffer_data_size);
@ -228,145 +119,94 @@ void load_index_buffer()
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_data_size, index_buffer_data, GL_STATIC_DRAW);
free(index_buffer_data);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void load_test_vertex_attributes()
void load_vertex_attributes(int i)
{
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
glBindBuffer(GL_ARRAY_BUFFER, per_vertex_buffer);
glVertexBindingDivisor(0, 0);
glVertexBindingDivisor(1, 1);
glVertexAttribPointer(location.attrib.position,
3,
GL_HALF_FLOAT,
GL_FALSE,
per_vertex_size,
(void*)(0)
);
glEnableVertexAttribArray(test_location.attrib.position);
glVertexAttribFormat(test_location.attrib.position, 3, GL_HALF_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(test_location.attrib.position, 0);
glVertexAttribPointer(location.attrib.normal,
3,
GL_HALF_FLOAT,
GL_FALSE,
per_vertex_size,
(void*)(6)
);
glEnableVertexAttribArray(test_location.attrib.normal);
glVertexAttribFormat(test_location.attrib.normal, 3, GL_HALF_FLOAT, GL_FALSE, 6);
glVertexAttribBinding(test_location.attrib.normal, 0);
glVertexAttribPointer(location.attrib.texture,
2,
GL_HALF_FLOAT,
GL_FALSE,
per_vertex_size,
(void*)(12)
);
glEnableVertexAttribArray(location.attrib.position);
glEnableVertexAttribArray(location.attrib.normal);
glEnableVertexAttribArray(location.attrib.texture);
glVertexAttribDivisor(location.attrib.position, 0);
glVertexAttribDivisor(location.attrib.normal, 0);
glVertexAttribDivisor(location.attrib.texture, 0);
glEnableVertexAttribArray(test_location.attrib.texture);
glVertexAttribFormat(test_location.attrib.texture, 2, GL_HALF_FLOAT, GL_FALSE, 12);
glVertexAttribBinding(test_location.attrib.texture, 0);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers[i]);
glEnableVertexAttribArray(test_location.attrib.block_position);
glVertexAttribFormat(test_location.attrib.block_position, 3, GL_SHORT, GL_FALSE, 0);
glVertexAttribBinding(test_location.attrib.block_position, 1);
glEnableVertexAttribArray(test_location.attrib.block_id);
glVertexAttribFormat(test_location.attrib.block_id, 1, GL_UNSIGNED_BYTE, GL_FALSE, 6);
glVertexAttribBinding(test_location.attrib.block_id, 1);
glEnableVertexAttribArray(test_location.attrib.data);
glVertexAttribFormat(test_location.attrib.data, 1, GL_UNSIGNED_BYTE, GL_FALSE, 7);
glVertexAttribBinding(test_location.attrib.data, 1);
glBindVertexArray(0);
glVertexAttribPointer(location.attrib.block_position,
3,
GL_SHORT,
GL_FALSE,
vertex_size,
(void*)(0)
);
glVertexAttribPointer(location.attrib.block_id,
1,
GL_UNSIGNED_BYTE,
GL_FALSE,
vertex_size,
(void*)(6)
);
glEnableVertexAttribArray(location.attrib.block_position);
glEnableVertexAttribArray(location.attrib.block_id);
glVertexAttribDivisor(location.attrib.block_position, 1);
glVertexAttribDivisor(location.attrib.block_id, 1);
}
void load_instance_cfg(int i)
{
int data_size;
void * data = read_file(vertex_paths[i].cfg, &data_size);
assert(data_size == (sizeof (struct instance_cfg)));
assert(data_size == 512);
memcpy(&instance_cfg[i], data, data_size);
}
struct target_name {
enum {
POSITION = 0,
NORMAL = 1,
COLOR = 2,
};
};
template <int render_target_count>
struct geometry_buffer {
unsigned int framebuffer;
unsigned int target[render_target_count]; // textures
unsigned int renderbuffer;
int initialized;
int width;
int height;
};
struct target_type {
GLint internal_format;
GLenum attachment;
};
static geometry_buffer<3> geometry_buffer_pnc = {};
static target_type const geometry_buffer_pnc_types[3] = {
[target_name::POSITION] = { GL_RGBA16F, GL_COLOR_ATTACHMENT0 },
[target_name::NORMAL] = { GL_RGBA16F, GL_COLOR_ATTACHMENT1 },
[target_name::COLOR] = { GL_RGBA8, GL_COLOR_ATTACHMENT2 },
};
template <int render_target_count>
void init_geometry_buffer(geometry_buffer<render_target_count>& geometry_buffer, target_type const * const types)
{
int width = g_window_width;
int height = g_window_height;
if ((geometry_buffer.initialized == 1) && (width == geometry_buffer.width) && (height == geometry_buffer.height)) {
return;
}
if (geometry_buffer.initialized) {
glDeleteFramebuffers(1, &geometry_buffer.framebuffer);
glDeleteTextures(render_target_count, geometry_buffer.target);
glDeleteRenderbuffers(1, &geometry_buffer.renderbuffer);
}
glGenFramebuffers(1, &geometry_buffer.framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, geometry_buffer.framebuffer);
glGenTextures(render_target_count, geometry_buffer.target);
for (int i = 0; i < render_target_count; i++) {
glBindTexture(GL_TEXTURE_2D, geometry_buffer.target[i]);
glTexImage2D(GL_TEXTURE_2D, 0, types[i].internal_format, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, types[i].attachment, GL_TEXTURE_2D, geometry_buffer.target[i], 0);
}
static_assert(render_target_count == 3);
GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments); // bound to GL_DRAW_FRAMEBUFFER
glGenRenderbuffers(1, &geometry_buffer.renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, geometry_buffer.renderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, geometry_buffer.renderbuffer);
assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
geometry_buffer.initialized = 1;
geometry_buffer.width = width;
geometry_buffer.height = height;
}
void load_buffers()
{
load_test_vertex_attributes();
// per-vertex buffer
glGenBuffers(1, &per_vertex_buffer);
load_per_vertex_buffer();
// per-instance buffer
glGenBuffers(region_count, per_instance_vertex_buffers);
glGenVertexArrays(region_count, vertex_array_objects);
glGenBuffers(region_count, vertex_buffers);
for (int i = 0; i < region_count; i++) {
load_per_instance_vertex_buffer(i);
glBindVertexArray(vertex_array_objects[i]);
load_vertex_buffer(i);
load_vertex_attributes(i);
load_instance_cfg(i);
}
// index buffer
glGenBuffers(1, &index_buffer);
load_index_buffer();
}
@ -391,144 +231,54 @@ void load_textures()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
free(texture_data);
glBindTexture(GL_TEXTURE_2D, 0);
}
static unsigned int light_uniform_buffer;
static unsigned int texture_id_uniform_buffer;
static unsigned int textures_ubo;
unsigned int load_uniform_buffer(char const * const path)
void load_texture_shader_storage()
{
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
int data_size;
void * data = read_file(path, &data_size);
assert(data != NULL);
int textures_data_size;
void * textures_data = read_file("minecraft/block_id_to_texture_id.data", &textures_data_size);
assert(textures_data != NULL);
glBufferData(GL_UNIFORM_BUFFER, data_size, data, GL_STATIC_DRAW);
free(data);
glBufferData(GL_UNIFORM_BUFFER, textures_data_size, textures_data, GL_STATIC_DRAW);
free(textures_data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
return buffer;
}
void load_light_uniform_buffer()
{
light_uniform_buffer = load_uniform_buffer("minecraft/global.lights.vtx");
}
void load_texture_id_uniform_buffer()
{
texture_id_uniform_buffer = load_uniform_buffer("minecraft/block_id_to_texture_id.data");
textures_ubo = buffer;
}
extern "C" {
void * SDL_GL_GetProcAddress(const char *proc);
}
struct view_state {
XMVECTOR up;
XMVECTOR eye;
XMVECTOR forward;
XMVECTOR direction;
float fov;
float pitch;
};
view_state view_state;
font::font * terminus_fonts;
void load(const char * source_path)
void load()
{
g_source_path_length = strlen(source_path);
assert(source_path[g_source_path_length - 1] != '/');
g_source_path = source_path;
fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress);
gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress);
load_test_program();
load_program();
load_buffers();
load_textures();
load_texture_id_uniform_buffer();
//load_texture_shader_storage();
view_state.up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
view_state.eye = XMVectorSet(-55.5f, 48.25f, 50.0f, 1);
view_state.forward = XMVectorSet(-0.63, 0.78, 0, 0);
view_state.direction = view_state.forward;
view_state.pitch = -0.11;
view_state.fov = 1.5;
//////////////////////////////////////////////////////////////////////
// font
//////////////////////////////////////////////////////////////////////
font::load_shader();
terminus_fonts = (font::font *)malloc((sizeof (font::font)) * font::terminus_length);
font::load_fonts(terminus_fonts, font::terminus, font::terminus_length);
//////////////////////////////////////////////////////////////////////
// quad
//////////////////////////////////////////////////////////////////////
load_quad_program();
load_quad_index_buffer();
//////////////////////////////////////////////////////////////////////
// lighting
//////////////////////////////////////////////////////////////////////
load_lighting_program();
load_light_uniform_buffer();
//unsigned int textures_layout = glGetUniformBlockIndex(test_program, "TexturesLayout");
//glUniformBlockBinding(test_program, textures_layout, 0);
//printf("textures_layout %d\n", textures_layout);
}
float _ry = 0.0;
static float vx = 0.0;
static float vy = 0.0;
static float vz = 0.0;
struct light_parameters {
float quadratic;
float linear;
};
light_parameters lighting = {
.quadratic = 1.0,
.linear = 1.0
};
void update(float lx, float ly, float rx, float ry, float tl, float tr,
int up, int down, int left, int right,
int a, int b, int x, int y)
void update(float lx, float ly, float ry)
{
//view_state.yaw += rx;
XMMATRIX mrz = XMMatrixRotationZ(rx * -0.035);
view_state.forward = XMVector3Transform(XMVector3NormalizeEst(view_state.forward), mrz);
XMVECTOR normal = XMVector3NormalizeEst(XMVector3Cross(view_state.forward, view_state.up));
view_state.pitch += ry * -0.035;
if (view_state.pitch > 1.57f) view_state.pitch = 1.57f;
if (view_state.pitch < -1.57f) view_state.pitch = -1.57f;
XMMATRIX mrn = XMMatrixRotationAxis(normal, view_state.pitch);
view_state.direction = XMVector3Transform(view_state.forward, mrn);
view_state.eye += view_state.forward * -ly + normal * lx + view_state.up * (tl - tr);
float new_fov = view_state.fov + 0.01 * up + -0.01 * down;
if (new_fov > 0.00001f) {
view_state.fov = new_fov;
}
lighting.quadratic += 0.01 * a + -0.01 * b;
if (lighting.quadratic < 0.0f)
lighting.quadratic = 0.0f;
lighting.linear += 0.01 * x + -0.01 * y;
if (lighting.linear < 0.0f)
lighting.linear = 0.0f;
vx += 2.5 * lx;
vy += -2.5 * ry;
vz += -2.5 * ly;
}
static inline int popcount(int x)
@ -536,107 +286,45 @@ static inline int popcount(int x)
return __builtin_popcount(x);
}
template <typename T>
void labeled_value(char * const buf, char const * const label, char const * const format, T value)
void draw()
{
const int label_length = strlen(label);
memcpy(buf, label, label_length);
int len = snprintf(&buf[label_length], 511 - label_length, format, value);
buf[label_length + len] = 0;
}
XMVECTOR eye = XMVectorSet(vx + -50.0f, vz + -50.0f, vy + 150.0f, 0.0f);
XMVECTOR at = XMVectorSet(vx + 50.0f, vz + 50.0f, vy + 50.0f, 0.0f);
XMVECTOR up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
XMMATRIX view = XMMatrixLookAtRH(eye, at, up);
inline static float draw_vector(font::font const& ter_best, char * const buf, float y, char const * const label, XMVECTOR vec)
{
labeled_value<float>(buf, label, ".x: %.2f", XMVectorGetX(vec));
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
labeled_value<float>(buf, label, ".y: %.2f", XMVectorGetY(vec));
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
labeled_value<float>(buf, label, ".z: %.2f", XMVectorGetZ(vec));
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
return y;
}
void draw_hud()
{
char buf[512];
float y = 10.0f;
int font_ix = font::best_font(font::terminus, font::terminus_length);
font::font const& ter_best = terminus_fonts[font_ix];
font::draw_start(ter_best, empty_vertex_array_object, quad_index_buffer);
labeled_value<float>(buf, "fov: ", "%.3f", view_state.fov);
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
labeled_value<int>(buf, "font_height: ", "%d", ter_best.desc->glyph_height);
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
labeled_value<float>(buf, "lighting.quadratic: ", "%.2f", lighting.quadratic);
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
labeled_value<float>(buf, "lighting.linear: ", "%.2f", lighting.linear);
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
y = draw_vector(ter_best, buf, y, "eye", view_state.eye);
y = draw_vector(ter_best, buf, y, "forward", view_state.forward);
labeled_value<float>(buf, "pitch: ", "%.9f", view_state.pitch);
font::draw_string(ter_best, buf, 10, y);
y += ter_best.desc->glyph_height;
}
void draw_minecraft()
{
// possibly re-initialize geometry buffer if window width/height changes
init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types);
XMVECTOR at = XMVectorAdd(view_state.eye, view_state.direction);
XMMATRIX view = XMMatrixLookAtRH(view_state.eye, at, view_state.up);
float fov_angle_y = XMConvertToRadians(45 * view_state.fov);
float aspect_ratio = g_window_width / g_window_height;
float fov_angle_y = XMConvertToRadians(45 * 0.75);
float aspect_ratio = 1.0;
float near_z = 1.0;
float far_z = 0.1;
XMMATRIX projection = XMMatrixPerspectiveFovRH(fov_angle_y, aspect_ratio, near_z, far_z);
XMMATRIX transform = view * projection;
glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
glClearDepth(-1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(test_program);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GREATER);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniformMatrix4fv(test_location.uniform.transform, 1, false, (float *)&transform);
glUniform1i(test_location.uniform.terrain_sampler, 0);
glUniformMatrix4fv(location.uniform.transform, 1, false, (float *)&transform);
glUniform1i(location.uniform.terrain_sampler, 0);
glBindBufferBase(GL_UNIFORM_BUFFER, test_location.binding.texture_id, texture_id_uniform_buffer);
//glBindBuffer(GL_UNIFORM_BUFFER, textures_ubo);
//glBindBufferBase(GL_UNIFORM_BUFFER, 0, textures_ubo);
//glEnable(GL_CULL_FACE);
//glCullFace(GL_FRONT);
//glFrontFace(GL_CCW);
glBindVertexArray(vertex_array_object);
glBindVertexBuffer(0, per_vertex_buffer, 0, per_vertex_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
for (int region_index = 0; region_index < region_count; region_index++) {
glBindVertexBuffer(1, per_instance_vertex_buffers[region_index], 0, vertex_size);
//////////////////////////////////////////////////////////////////////
// cube blocks
//////////////////////////////////////////////////////////////////////
glBindVertexArray(vertex_array_objects[region_index]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
for (int configuration = 1; configuration < 64; configuration++) {
int element_count = 6 * popcount(configuration);
const void * indices = (void *)((ptrdiff_t)index_buffer_configuration_offsets[configuration]); // index into configuration.idx
@ -649,91 +337,5 @@ void draw_minecraft()
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count, base_instance);
}
//////////////////////////////////////////////////////////////////////
// custom blocks
//////////////////////////////////////////////////////////////////////
for (int i = 0; i < custom_block_types; i++) {
int element_count = index_buffer_custom_offsets[i].count;
const void * indices = (void *)((ptrdiff_t)index_buffer_custom_offsets[i].offset);
int instance_count = instance_cfg[region_index].cfg[64 + i].instance_count;
int base_instance = instance_cfg[region_index].cfg[64 + i].offset / vertex_size; // index into region.0.0.instance.vtx
if (instance_count == 0)
continue;
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count, base_instance);
}
}
}
void draw_quad()
{
glUseProgram(quad_program);
glDepthFunc(GL_ALWAYS);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[1]);
glUniform1i(quad_location.uniform.texture_sampler, 0);
glBindVertexArray(empty_vertex_array_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
}
static inline bool near_zero(float a)
{
return (fabsf(a) < 0.00001f);
}
void draw_lighting()
{
glUseProgram(lighting_program);
glDepthFunc(GL_ALWAYS);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[1]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[2]);
glUniform1i(lighting_location.uniform.position_sampler, 0);
glUniform1i(lighting_location.uniform.normal_sampler, 1);
glUniform1i(lighting_location.uniform.color_sampler, 2);
float quadratic = near_zero(lighting.quadratic) ? 0.0 : 1.0f / lighting.quadratic;
float linear = near_zero(lighting.linear) ? 0.0 : 1.0f / lighting.linear;
glUniform1f(lighting_location.uniform.quadratic, quadratic);
glUniform1f(lighting_location.uniform.linear, linear);
XMFLOAT3 eye;
XMStoreFloat3(&eye, view_state.eye);
glUniform3fv(lighting_location.uniform.eye, 1, (float*)&eye);
glBindBufferBase(GL_UNIFORM_BUFFER, lighting_location.binding.lights, light_uniform_buffer);
glBindVertexArray(empty_vertex_array_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
}
void draw()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(-1.0f);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, geometry_buffer_pnc.framebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_minecraft();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_lighting();
//draw_quad();
draw_hud();
}

View File

@ -1,10 +0,0 @@
#include "window.h"
float g_window_width = 1;
float g_window_height = 1;
void update_window(int width, int height)
{
g_window_width = width;
g_window_height = height;
}