Compare commits

...

1 Commits

Author SHA1 Message Date
86890e2a77 minecraft: render via geometry shader 2026-03-06 14:57:58 -06:00
19 changed files with 612 additions and 672 deletions

3
.gitignore vendored
View File

@ -5,4 +5,5 @@
*.o *.o
main main
*.so *.so
*.dylib *.dylib
__pycache__

View File

@ -7,6 +7,7 @@ extern "C" {
void * read_file(const char * filename, int * out_size); void * read_file(const char * filename, int * out_size);
unsigned int compile_from_files(const char * vertex_path, unsigned int compile_from_files(const char * vertex_path,
const char * geometry_path,
const char * fragment_path); const char * fragment_path);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -40,9 +40,6 @@ function love.run()
return a or 0, b return a or 0, b
end end
end end
if name == "keypressed" then
keypressed(a, b, c)
end
end end
local dt = love.timer.step() local dt = love.timer.step()
@ -52,5 +49,7 @@ function love.run()
love.graphics.present() love.graphics.present()
love.timer.sleep(0.001) love.timer.sleep(0.001)
local fps = love.timer.getFPS( )
print(fps)
end end
end end

View File

@ -101,4 +101,6 @@ with open("block_id_to_texture_id.data", "wb") as f:
for i in range(256): for i in range(256):
value = lookup.get(i, unk) value = lookup.get(i, unk)
f.write(struct.pack("<i", value)) f.write(struct.pack("<i", value))
print(str(value)+',') print(str(value).rjust(3), end=', ')
if i % 16 == 15:
print()

View File

@ -1,238 +1,11 @@
# https://minecraft.fandom.com/wiki/Region_file_format
# https://minecraft.wiki/w/NBT_format#Binary_format
# https://minecraft.wiki/w/Chunk_format/McRegion
import sys import sys
import struct import struct
from pprint import pprint from pprint import pprint
import zlib
import enum
from dataclasses import dataclass
from itertools import chain from itertools import chain
def _parse_locations(mem, offset): import mcregion
for i in range(1024): import vec3
ix = offset + i * 4 import vertex_buffer
chunk_location, = struct.unpack(">I", mem[ix:ix+4])
chunk_offset = (chunk_location >> 8) & 0xffffff
chunk_sector_count = chunk_location & 0xff
yield chunk_offset, chunk_sector_count
def parse_locations(mem, offset):
locations = list(_parse_locations(mem, offset))
return offset + 1024 * 4, locations
def _parse_timestamps(mem, offset):
for i in range(1024):
ix = offset + i * 4
timestamp, = struct.unpack(">I", mem[ix:ix+4])
yield timestamp
def parse_timestamps(mem, offset):
timestamps = list(_parse_timestamps(mem, offset))
return offset + 1024 * 4, timestamps
def print_locations(locations):
for y in range(32):
for x in range(32):
offset, count = locations[y * 32 + x]
print(str(offset).rjust(4), end=' ')
print()
class CountZeroException(Exception):
pass
def parse_payload(mem, location):
offset, count = location
if count == 0:
raise CountZeroException()
ix = offset * 4096
payload = mem[ix:ix + count * 4096]
length, = struct.unpack(">I", payload[0:4])
assert length <= count * 4096, (length, count)
compression_type = payload[4]
data = payload[5:5 + (length - 1)]
assert compression_type == 2, compression_type
uncompressed = zlib.decompress(data)
return memoryview(uncompressed)
class TAG:
Byte = 0x01
Short = 0x02
Int = 0x03
Long = 0x04
Float = 0x05
Double = 0x06
ByteArray = 0x07
String = 0x08
List = 0x09
Compound = 0x0a
@dataclass
class Byte:
name: str
value: int
@dataclass
class Short:
name: str
value: int
@dataclass
class Int:
name: str
value: int
@dataclass
class Long:
name: str
value: int
@dataclass
class Float:
name: str
value: float
@dataclass
class Double:
name: str
value: float
@dataclass
class ByteArray:
name: str
value: bytes
@dataclass
class String:
name: str
value: str
@dataclass
class List:
name: str
items: list
@dataclass
class Compound:
name: str
tags: list
def indent(level):
return " " * level
def parse_tag_inner(mem, offset, level, tag_type, name):
payload = mem[offset:]
if tag_type == TAG.Byte:
value, = struct.unpack(">b", payload[0:1])
return offset + 1, Byte(name, value)
if tag_type == TAG.Short:
value, = struct.unpack(">h", payload[0:2])
return offset + 2, Short(name, value)
elif tag_type == TAG.Int:
value, = struct.unpack(">i", payload[0:4])
return offset + 4, Int(name, value)
elif tag_type == TAG.Long:
value, = struct.unpack(">q", payload[0:8])
return offset + 8, Long(name, value)
elif tag_type == TAG.Float:
value, = struct.unpack(">f", payload[0:4])
return offset + 4, Float(name, value)
elif tag_type == TAG.Double:
value, = struct.unpack(">d", payload[0:8])
return offset + 8, Double(name, value)
elif tag_type == TAG.ByteArray:
size, = struct.unpack(">i", payload[0:4])
value = bytes(payload[4:4+size])
return offset + 4 + size, ByteArray(name, value)
elif tag_type == TAG.String:
size, = struct.unpack(">H", payload[0:2])
value = bytes(payload[2:2+size]).decode('utf-8')
return offset + 2 + size, String(name, value)
elif tag_type == TAG.List:
list_content_tag_id, size = struct.unpack(">BI", payload[0:5])
items = []
offset = offset + 5
for i in range(size):
payload = mem[offset:]
offset, item = parse_tag_inner(mem, offset, level, list_content_tag_id, None)
items.append(item)
return offset, List(name, items)
elif tag_type == TAG.Compound:
tags = []
while payload[0] != 0:
offset, tag = parse_tag(mem, offset, level+1)
payload = mem[offset:]
tags.append(tag)
return offset + 1, Compound(name, tags)
else:
assert False, tag_type
def parse_tag(mem, offset, level):
data = mem[offset:]
tag_type = data[0]
name_length, = struct.unpack(">H", data[1:3])
name = bytes(data[3:3+name_length])
#print(indent(level), tag_type, name_length, name)
offset = offset + 3 + name_length
return parse_tag_inner(mem, offset, level, tag_type, name)
@dataclass
class Level:
blocks: bytes
data: bytes
sky_light: bytes
block_light: bytes
height_map: bytes
x_pos: int
z_pos: int
def level_from_tag(tag):
assert type(tag) == Compound
assert tag.name == b''
assert len(tag.tags) == 1
level, = tag.tags
assert type(level) == Compound
assert level.name == b'Level'
name_mapping = {
b'Blocks': 'blocks',
b'Data': 'data',
b'SkyLight': 'sky_light',
b'BlockLight': 'block_light',
b'HeightMap': 'height_map',
b'xPos': 'x_pos',
b'zPos': 'z_pos',
}
args = {}
for tag in level.tags:
if tag.name in name_mapping:
arg_name = name_mapping[tag.name]
args[arg_name] = tag.value
return Level(**args)
def parse_location(mem, location):
uncompressed = parse_payload(mem, location)
offset, tag = parse_tag(uncompressed, 0, 0)
assert offset == len(uncompressed), (offset, len(uncompressed))
level = level_from_tag(tag)
return level
def xyz_from_block_index(block_index):
assert block_index >= 0 and block_index < (128 * 16 * 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):
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)
def wrap_n(nc, chunk_c): def wrap_n(nc, chunk_c):
if nc < 0: if nc < 0:
@ -243,77 +16,15 @@ def wrap_n(nc, chunk_c):
chunk_c = chunk_c + 1 chunk_c = chunk_c + 1
return nc, chunk_c return nc, chunk_c
def vec3_add(v1, v2): normals = [
return ( (-1.0, 0.0, 0.0),
v1[0] + v2[0], (0.0, -1.0, 0.0),
v1[1] + v2[1], (0.0, 0.0, -1.0),
v1[2] + v2[2], (0.0, 0.0, 1.0),
) (0.0, 1.0, 0.0),
(1.0, 0.0, 0.0),
def vec3_mul(v, s):
return (
v[0] * s,
v[1] * s,
v[2] * s,
)
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]
}
vertex_buffer = {}
def add_vertex(vertex):
if vertex in vertex_buffer:
return vertex_buffer[vertex]
else:
index = len(vertex_buffer)
vertex_buffer[vertex] = index
return index
def emit_face(center_position, block_id, triangles):
for index in triangles:
position, normal, texture = vertex_table[index]
position = vec3_add(vec3_mul(position, 0.5), center_position)
vertex = (position, normal, texture, block_id)
new_index = add_vertex(vertex)
yield new_index
def block_neighbors(level_table, chunk_x, chunk_z, block_index): def block_neighbors(level_table, chunk_x, chunk_z, block_index):
block_id = level_table[(chunk_x, chunk_z)].blocks[block_index] block_id = level_table[(chunk_x, chunk_z)].blocks[block_index]
if block_id == 0: if block_id == 0:
@ -328,36 +39,65 @@ def block_neighbors(level_table, chunk_x, chunk_z, block_index):
return True return True
if nz > 15 or nz < 0: if nz > 15 or nz < 0:
return True return True
n_block_index = block_index_from_xyz(nx, ny, nz) n_block_index = mcregion.block_index_from_xyz(nx, ny, nz)
key = (n_chunk_x, n_chunk_z) key = (n_chunk_x, n_chunk_z)
if key not in level_table: if key not in level_table:
return True return True
n_block_id = level_table[key].blocks[n_block_index] n_block_id = level_table[key].blocks[n_block_index]
return n_block_id != 0 return n_block_id != 0
x, y, z = xyz_from_block_index(block_index) x, y, z = mcregion.xyz_from_block_index(block_index)
center_position = vec3_add((x, y, z), (chunk_x * 16, 0, chunk_z * 16)) center_position = vec3.add((x, y, z), (chunk_x * 16, 0, chunk_z * 16))
for normal, triangles in faces_by_normal.items(): def find_non_neighbors():
neighbor = vec3_add(normal, (x, y, z)) for i, normal in enumerate(normals):
if not neighbor_exists(*neighbor): neighbor = vec3.add(normal, (x, y, z))
yield from emit_face(center_position, block_id, triangles) if not neighbor_exists(*neighbor):
yield i
#yield chunk_x, chunk_z, block_index, block_id normal_indices = list(find_non_neighbors())
#break if normal_indices:
yield center_position, block_id, normal_indices
def devoxelize_region(level_table): def devoxelize_region(level_table):
for chunk_x, chunk_z in level_table.keys(): for chunk_x, chunk_z in level_table.keys():
for block_index in range(128 * 16 * 16): for block_index in range(128 * 16 * 16):
yield from block_neighbors(level_table, chunk_x, chunk_z, block_index) yield from block_neighbors(level_table, chunk_x, chunk_z, block_index)
from collections import defaultdict def build_level_table(mem, locations):
counts = defaultdict(int) level_table = {}
for location in locations:
try:
level = mcregion.parse_location(mem, location)
except CountZeroException:
continue
x, z = level.x_pos, level.z_pos
level_table[(x, z)] = level
return level_table
def linearized_vertex_buffer(): def normal_indices_as_block_configuration(normal_indices):
for vertex, i in sorted(vertex_buffer.items(), key=lambda kv: kv[1]): acc = 0
yield vertex for i in normal_indices:
acc |= (1 << i)
return acc
def build_block_configuration_table():
for i in range(64):
indices = []
for j in range(6):
if ((i >> j) & 1) != 0:
indices.extend(vertex_buffer.faces_by_normal[normals[j]])
yield indices
def build_block_instances(f, blocks):
for position, block_id, normal_indices in blocks:
block_configuration = normal_indices_as_block_configuration(normal_indices)
#print(position, block_id, block_configuration)
f.write(struct.pack("<hhhBB",
position[0], position[1], position[2],
block_id,
block_configuration))
def main(mcr_path, data_path): def main(mcr_path, data_path):
with open(mcr_path, "rb") as f: with open(mcr_path, "rb") as f:
@ -365,35 +105,17 @@ def main(mcr_path, data_path):
mem = memoryview(buf) mem = memoryview(buf)
offset = 0 offset = 0
offset, locations = parse_locations(mem, offset) offset, locations = mcregion.parse_locations(mem, offset)
offset, timestamps = parse_timestamps(mem, offset) offset, timestamps = mcregion.parse_timestamps(mem, offset)
assert offset == 0x2000 assert offset == 0x2000
level_table = {} level_table = build_level_table(mem, locations)
for location in locations: blocks = devoxelize_region(level_table)
try:
level = parse_location(mem, location)
except CountZeroException:
continue
x, z = level.x_pos, level.z_pos
level_table[(x, z)] = level
#with open(f"blocks__{x:02x}_{z:02x}.data", "wb") as f:
# f.write(level.blocks)
with open(data_path + ".idx", "wb") as f:
for index in devoxelize_region(level_table):
f.write(struct.pack("<I", index))
with open(data_path + ".vtx", "wb") as f: with open(data_path + ".vtx", "wb") as f:
for vertex in linearized_vertex_buffer(): build_block_instances(f, blocks)
vertex = [*vertex[0], *vertex[1], *vertex[2], vertex[3]]#, vertex[3]]
f.write(struct.pack("<fffffffff", *vertex))
#for chunk_x, chunk_z, block_index, block_id in devoxelize_region(level_table): #pprint(list(build_block_configuration_table()))
# #print(chunk_x, chunk_z, block_id)
# counts[block_id] += 1
# f.write(struct.pack("<bbBb", chunk_x, chunk_z, block_id, 0))
# f.write(struct.pack("<i", block_index))
mcr_path = sys.argv[1] mcr_path = sys.argv[1]
data_path = sys.argv[2] data_path = sys.argv[2]

231
minecraft/gen/mcregion.py Normal file
View File

@ -0,0 +1,231 @@
from dataclasses import dataclass
import struct
import zlib
# https://minecraft.fandom.com/wiki/Region_file_format
# https://minecraft.wiki/w/NBT_format#Binary_format
# https://minecraft.wiki/w/Chunk_format/McRegion
def _parse_locations(mem, offset):
for i in range(1024):
ix = offset + i * 4
chunk_location, = struct.unpack(">I", mem[ix:ix+4])
chunk_offset = (chunk_location >> 8) & 0xffffff
chunk_sector_count = chunk_location & 0xff
yield chunk_offset, chunk_sector_count
def parse_locations(mem, offset):
locations = list(_parse_locations(mem, offset))
return offset + 1024 * 4, locations
def _parse_timestamps(mem, offset):
for i in range(1024):
ix = offset + i * 4
timestamp, = struct.unpack(">I", mem[ix:ix+4])
yield timestamp
def parse_timestamps(mem, offset):
timestamps = list(_parse_timestamps(mem, offset))
return offset + 1024 * 4, timestamps
def print_locations(locations):
for y in range(32):
for x in range(32):
offset, count = locations[y * 32 + x]
print(str(offset).rjust(4), end=' ')
print()
class CountZeroException(Exception):
pass
def parse_payload(mem, location):
offset, count = location
if count == 0:
raise CountZeroException()
ix = offset * 4096
payload = mem[ix:ix + count * 4096]
length, = struct.unpack(">I", payload[0:4])
assert length <= count * 4096, (length, count)
compression_type = payload[4]
data = payload[5:5 + (length - 1)]
assert compression_type == 2, compression_type
uncompressed = zlib.decompress(data)
return memoryview(uncompressed)
class TAG:
Byte = 0x01
Short = 0x02
Int = 0x03
Long = 0x04
Float = 0x05
Double = 0x06
ByteArray = 0x07
String = 0x08
List = 0x09
Compound = 0x0a
@dataclass
class Byte:
name: str
value: int
@dataclass
class Short:
name: str
value: int
@dataclass
class Int:
name: str
value: int
@dataclass
class Long:
name: str
value: int
@dataclass
class Float:
name: str
value: float
@dataclass
class Double:
name: str
value: float
@dataclass
class ByteArray:
name: str
value: bytes
@dataclass
class String:
name: str
value: str
@dataclass
class List:
name: str
items: list
@dataclass
class Compound:
name: str
tags: list
def indent(level):
return " " * level
def parse_tag_inner(mem, offset, level, tag_type, name):
payload = mem[offset:]
if tag_type == TAG.Byte:
value, = struct.unpack(">b", payload[0:1])
return offset + 1, Byte(name, value)
if tag_type == TAG.Short:
value, = struct.unpack(">h", payload[0:2])
return offset + 2, Short(name, value)
elif tag_type == TAG.Int:
value, = struct.unpack(">i", payload[0:4])
return offset + 4, Int(name, value)
elif tag_type == TAG.Long:
value, = struct.unpack(">q", payload[0:8])
return offset + 8, Long(name, value)
elif tag_type == TAG.Float:
value, = struct.unpack(">f", payload[0:4])
return offset + 4, Float(name, value)
elif tag_type == TAG.Double:
value, = struct.unpack(">d", payload[0:8])
return offset + 8, Double(name, value)
elif tag_type == TAG.ByteArray:
size, = struct.unpack(">i", payload[0:4])
value = bytes(payload[4:4+size])
return offset + 4 + size, ByteArray(name, value)
elif tag_type == TAG.String:
size, = struct.unpack(">H", payload[0:2])
value = bytes(payload[2:2+size]).decode('utf-8')
return offset + 2 + size, String(name, value)
elif tag_type == TAG.List:
list_content_tag_id, size = struct.unpack(">BI", payload[0:5])
items = []
offset = offset + 5
for i in range(size):
payload = mem[offset:]
offset, item = parse_tag_inner(mem, offset, level, list_content_tag_id, None)
items.append(item)
return offset, List(name, items)
elif tag_type == TAG.Compound:
tags = []
while payload[0] != 0:
offset, tag = parse_tag(mem, offset, level+1)
payload = mem[offset:]
tags.append(tag)
return offset + 1, Compound(name, tags)
else:
assert False, tag_type
def parse_tag(mem, offset, level):
data = mem[offset:]
tag_type = data[0]
name_length, = struct.unpack(">H", data[1:3])
name = bytes(data[3:3+name_length])
#print(indent(level), tag_type, name_length, name)
offset = offset + 3 + name_length
return parse_tag_inner(mem, offset, level, tag_type, name)
@dataclass
class Level:
blocks: bytes
data: bytes
sky_light: bytes
block_light: bytes
height_map: bytes
x_pos: int
z_pos: int
def level_from_tag(tag):
assert type(tag) == Compound
assert tag.name == b''
assert len(tag.tags) == 1
level, = tag.tags
assert type(level) == Compound
assert level.name == b'Level'
name_mapping = {
b'Blocks': 'blocks',
b'Data': 'data',
b'SkyLight': 'sky_light',
b'BlockLight': 'block_light',
b'HeightMap': 'height_map',
b'xPos': 'x_pos',
b'zPos': 'z_pos',
}
args = {}
for tag in level.tags:
if tag.name in name_mapping:
arg_name = name_mapping[tag.name]
args[arg_name] = tag.value
return Level(**args)
def parse_location(mem, location):
uncompressed = parse_payload(mem, location)
offset, tag = parse_tag(uncompressed, 0, 0)
assert offset == len(uncompressed), (offset, len(uncompressed))
level = level_from_tag(tag)
return level
def xyz_from_block_index(block_index):
assert block_index >= 0 and block_index < (128 * 16 * 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):
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)

BIN
minecraft/gen/region.idx Normal file

Binary file not shown.

13
minecraft/gen/vec3.py Normal file
View File

@ -0,0 +1,13 @@
def add(v1, v2):
return (
v1[0] + v2[0],
v1[1] + v2[1],
v1[2] + v2[2],
)
def mul(v, s):
return (
v[0] * s,
v[1] * s,
v[2] * s,
)

View File

@ -0,0 +1,64 @@
import vec3
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]
}
vertex_buffer = {}
def add_vertex(vertex):
if vertex in vertex_buffer:
return vertex_buffer[vertex]
else:
index = len(vertex_buffer)
vertex_buffer[vertex] = index
return index
def emit_face(center_position, block_id, triangles):
for index in triangles:
position, normal, texture = vertex_table[index]
position = vec3.add(vec3.mul(position, 0.5), center_position)
vertex = (position, normal, texture, block_id)
new_index = add_vertex(vertex)
yield new_index
def linearized_vertex_buffer():
for vertex, i in sorted(vertex_buffer.items(), key=lambda kv: kv[1]):
yield vertex
#with open(data_path + ".vtx", "wb") as f:
# for vertex in linearized_vertex_buffer():
# vertex = [*vertex[0], *vertex[1], *vertex[2], vertex[3]]#, vertex[3]]
# f.write(struct.pack("<fffffffff", *vertex))

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,286 +1,44 @@
#version 330 core #version 330 core
in vec3 PixelNormal; in GS_OUT {
in vec2 PixelTexture; vec3 Normal;
in float PixelBlock; vec2 Texture;
flat int BlockID;
} gs_out;
out vec4 FragColor; out vec4 FragColor;
uniform sampler2D TerrainSampler; uniform sampler2D TerrainSampler;
/*layout (std140) uniform TexturesLayout
{
uint Textures[256];
};*/
int Textures[256] = int[256]( int Textures[256] = int[256](
185, 185, 1, 0, 2, 16, 4, 15, 17, 205, 205, 237, 237, 18, 19, 32, 33,
1, 34, 20, 52, 48, 49, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 0,
0, 185, 185, 185, 64, 185, 13, 12, 29, 28, 39, 38, 5, 5, 7, 8, 35,
2, 36, 37, 80, 31, 65, 4, 27, 84, 50, 40, 43, 88, 87, 44, 61, 185,
16, 81, 83, 128, 16, 185, 96, 6, 82, 6, 51, 51, 115, 99, 185, 66, 67,
4, 66, 70, 72, 73, 74, 4, 102, 103, 104, 105, 14, 102, 185, 185, 185, 185,
15, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
17, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
205, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
205, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
237, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
237, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
18, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
19, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
32, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
33, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185
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() void main()
{ {
vec3 light_direction = normalize(vec3(-1, -0.5, 0.5)); vec3 light_direction = normalize(vec3(-1, -0.5, 0.5));
float diffuse_intensity = max(dot(normalize(PixelNormal), light_direction), 0.0); float diffuse_intensity = max(dot(normalize(gs_out.Normal), light_direction), 0.0);
int terrain_ix = int(Textures[int(PixelBlock)]); int terrain_ix = int(Textures[int(gs_out.BlockID)]);
int terrain_x = terrain_ix % 16; int terrain_x = terrain_ix % 16;
int terrain_y = terrain_ix / 16; int terrain_y = terrain_ix / 16;
ivec2 coord = ivec2(terrain_x, terrain_y) * 16; ivec2 coord = ivec2(terrain_x, terrain_y) * 16;
coord += ivec2(PixelTexture.xy * 16.0); coord += ivec2(gs_out.Texture.xy * 16.0);
vec4 texture_color = texelFetch(TerrainSampler, coord, 0); vec4 texture_color = texelFetch(TerrainSampler, coord, 0);
if (texture_color.w != 1.0) { if (texture_color.w != 1.0) {
@ -288,7 +46,7 @@ void main()
return; return;
} }
if (int(PixelBlock) == 18) // leaves if (int(gs_out.BlockID) == 18) // leaves
texture_color.xyz *= vec3(0.125, 0.494, 0.027); texture_color.xyz *= vec3(0.125, 0.494, 0.027);
FragColor = vec4(texture_color.xyz * vec3(diffuse_intensity), 1.0); FragColor = vec4(texture_color.xyz * vec3(diffuse_intensity), 1.0);

100
shader/test.geom Normal file
View File

@ -0,0 +1,100 @@
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 24) out;
in VS_OUT {
int BlockID;
int Configuration;
} gs_in[1];
out GS_OUT {
vec3 Normal;
vec2 Texture;
flat int BlockID;
} gs_out;
struct PT {
vec3 Position;
vec2 Texture;
};
uniform mat4 Transform;
PT vertices[] = PT[24](
PT(vec3(-1.0, 1.0, -1.0), vec2(1.0, 0.0)),
PT(vec3(1.0, 1.0, 1.0), vec2(0.0, 1.0)),
PT(vec3(1.0, 1.0, -1.0), vec2(0.0, 0.0)),
PT(vec3(1.0, 1.0, 1.0), vec2(1.0, 1.0)),
PT(vec3(-1.0, -1.0, 1.0), vec2(0.0, 0.0)),
PT(vec3(1.0, -1.0, 1.0), vec2(1.0, 0.0)),
PT(vec3(-1.0, 1.0, 1.0), vec2(1.0, 1.0)),
PT(vec3(-1.0, -1.0, -1.0), vec2(0.0, 0.0)),
PT(vec3(-1.0, -1.0, 1.0), vec2(1.0, 0.0)),
PT(vec3(1.0, -1.0, -1.0), vec2(1.0, 0.0)),
PT(vec3(-1.0, -1.0, 1.0), vec2(0.0, 1.0)),
PT(vec3(-1.0, -1.0, -1.0), vec2(0.0, 0.0)),
PT(vec3(1.0, 1.0, -1.0), vec2(1.0, 1.0)),
PT(vec3(1.0, -1.0, 1.0), vec2(0.0, 0.0)),
PT(vec3(1.0, -1.0, -1.0), vec2(1.0, 0.0)),
PT(vec3(-1.0, 1.0, -1.0), vec2(1.0, 1.0)),
PT(vec3(1.0, -1.0, -1.0), vec2(0.0, 0.0)),
PT(vec3(-1.0, -1.0, -1.0), vec2(1.0, 0.0)),
PT(vec3(-1.0, 1.0, 1.0), vec2(1.0, 1.0)),
PT(vec3(-1.0, 1.0, 1.0), vec2(0.0, 1.0)),
PT(vec3(-1.0, 1.0, -1.0), vec2(0.0, 1.0)),
PT(vec3(1.0, -1.0, 1.0), vec2(1.0, 1.0)),
PT(vec3(1.0, 1.0, 1.0), vec2(0.0, 1.0)),
PT(vec3(1.0, 1.0, -1.0), vec2(0.0, 1.0))
);
int face_1[4] = int[4](8, 6, 7, 20);
int face_2[4] = int[4](11, 9, 10, 21);
int face_4[4] = int[4](17, 15, 16, 23);
int face_8[4] = int[4](5, 3, 4, 19);
int face_16[4] = int[4](2, 0, 1, 18);
int face_32[4] = int[4](14, 12, 13, 22);
vec4 transform(vec3 p)
{
return Transform * vec4(p.xzy, 1.0);
}
void emit_face(vec3 normal, int face[4])
{
vec3 position = gl_in[0].gl_Position.xyz;
PT vtx0 = vertices[face[0]];
gl_Position = transform(position + vtx0.Position * 0.5);
gs_out.Normal = normal.xzy;
gs_out.Texture = vtx0.Texture;
EmitVertex();
PT vtx1 = vertices[face[1]];
gl_Position = transform(position + vtx1.Position * 0.5);
gs_out.Normal = normal.xzy;
gs_out.Texture = vtx1.Texture;
EmitVertex();
PT vtx2 = vertices[face[2]];
gl_Position = transform(position + vtx2.Position * 0.5);
gs_out.Normal = normal.xzy;
gs_out.Texture = vtx2.Texture;
EmitVertex();
PT vtx3 = vertices[face[3]];
gl_Position = transform(position + vtx3.Position * 0.5);
gs_out.Normal = normal.xzy;
gs_out.Texture = vtx3.Texture;
EmitVertex();
EndPrimitive();
}
void main()
{
gs_out.BlockID = gs_in[0].BlockID;
int configuration = gs_in[0].Configuration;
if ((configuration & 1) != 0) emit_face(vec3(-1.0, 0.0, 0.0), face_1);
if ((configuration & 2) != 0) emit_face(vec3(0.0, -1.0, 0.0), face_2);
if ((configuration & 4) != 0) emit_face(vec3(0.0, 0.0, -1.0), face_4);
if ((configuration & 8) != 0) emit_face(vec3(0.0, 0.0, 1.0), face_8);
if ((configuration & 16) != 0) emit_face(vec3(0.0, 1.0, 0.0), face_16);
if ((configuration & 32) != 0) emit_face(vec3(1.0, 0.0, 0.0), face_32);
}

View File

@ -1,23 +1,20 @@
#version 330 core #version 330 core
layout (location = 0) in vec3 Position; layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal; layout (location = 1) in float BlockID;
layout (location = 2) in vec3 Texture; layout (location = 2) in float Configuration;
out vec3 PixelNormal; out VS_OUT {
out vec2 PixelTexture; int BlockID;
out float PixelBlock; int Configuration;
} vs_out;
uniform mat4 Transform; uniform mat4 Transform;
void main() void main()
{ {
//gl_Position = vec4(position, 1.0); vs_out.BlockID = int(BlockID);
//ourColor = color; vs_out.Configuration = int(Configuration);
PixelNormal = Normal.xzy; gl_Position = vec4(Position.xyz, 1.0);
PixelTexture = Texture.xy;
PixelBlock = Texture.z;
gl_Position = Transform * vec4(Position.xzy, 1.0);
} }

View File

@ -49,14 +49,22 @@ void * read_file(const char * filename, int * out_size)
unsigned int compile(const char * vertex_source, unsigned int compile(const char * vertex_source,
int vertex_source_size, int vertex_source_size,
const char * geometry_source,
int geometry_source_size,
const char * fragment_source, const char * fragment_source,
int fragment_source_size) int fragment_source_size)
{ {
int compile_status; int compile_status;
char info_log[512]; char info_log[512];
// program
unsigned int shader_program = glCreateProgram();
unsigned int vertex_shader = -1;
unsigned int geometry_shader = -1;
unsigned int fragment_shader = -1;
// vertex shader // vertex shader
unsigned int vertex_shader = glCreateShader(GL_VERTEX_SHADER); vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_source, &vertex_source_size); glShaderSource(vertex_shader, 1, &vertex_source, &vertex_source_size);
glCompileShader(vertex_shader); glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compile_status); glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compile_status);
@ -64,9 +72,23 @@ unsigned int compile(const char * vertex_source,
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log); glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
fprintf(stderr, "vertex shader compile: %s\n", info_log); fprintf(stderr, "vertex shader compile: %s\n", info_log);
} }
glAttachShader(shader_program, vertex_shader);
// geometry shader
if (geometry_source_size != 0) {
geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geometry_shader, 1, &geometry_source, &geometry_source_size);
glCompileShader(geometry_shader);
glGetShaderiv(geometry_shader, GL_COMPILE_STATUS, &compile_status);
if (!compile_status) {
glGetShaderInfoLog(geometry_shader, 512, NULL, info_log);
fprintf(stderr, "geometry shader compile: %s\n", info_log);
}
glAttachShader(shader_program, geometry_shader);
}
// fragment shader // fragment shader
unsigned int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_source, &fragment_source_size); glShaderSource(fragment_shader, 1, &fragment_source, &fragment_source_size);
glCompileShader(fragment_shader); glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &compile_status); glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &compile_status);
@ -74,11 +96,9 @@ unsigned int compile(const char * vertex_source,
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log); glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
fprintf(stderr, "fragment shader compile: %s\n", info_log); fprintf(stderr, "fragment shader compile: %s\n", info_log);
} }
glAttachShader(shader_program, fragment_shader);
// link shaders // link shaders
unsigned int shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program); glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &compile_status); glGetProgramiv(shader_program, GL_LINK_STATUS, &compile_status);
if (!compile_status) { if (!compile_status) {
@ -87,25 +107,41 @@ unsigned int compile(const char * vertex_source,
} }
glDeleteShader(vertex_shader); glDeleteShader(vertex_shader);
if (geometry_source_size != 0)
glDeleteShader(geometry_shader);
glDeleteShader(fragment_shader); glDeleteShader(fragment_shader);
return shader_program; return shader_program;
} }
unsigned int compile_from_files(const char * vertex_path, unsigned int compile_from_files(const char * vertex_path,
const char * geometry_path,
const char * fragment_path) const char * fragment_path)
{ {
int vertex_source_size; int vertex_source_size = 0;
char * vertex_source = read_file(vertex_path, &vertex_source_size); char * vertex_source = NULL;
int geometry_source_size = 0;
char * geometry_source = NULL;
int fragment_source_size = 0;
char * fragment_source = NULL;
vertex_source = read_file(vertex_path, &vertex_source_size);
assert(vertex_source != NULL); assert(vertex_source != NULL);
int fragment_source_size;
char * fragment_source = read_file(fragment_path, &fragment_source_size); if (geometry_path != NULL) {
geometry_source = read_file(geometry_path, &geometry_source_size);
assert(geometry_source != NULL);
}
fragment_source = read_file(fragment_path, &fragment_source_size);
assert(fragment_source != NULL); assert(fragment_source != NULL);
unsigned int program = compile(vertex_source, vertex_source_size, unsigned int program = compile(vertex_source, vertex_source_size,
geometry_source, geometry_source_size,
fragment_source, fragment_source_size); fragment_source, fragment_source_size);
free(vertex_source); free(vertex_source);
free(geometry_source);
free(fragment_source); free(fragment_source);
return program; return program;

View File

@ -9,8 +9,8 @@
struct location { struct location {
struct { struct {
unsigned int position; unsigned int position;
unsigned int normal; unsigned int block_id;
unsigned int texture; unsigned int configuration;
} attrib; } attrib;
struct { struct {
unsigned int transform; unsigned int transform;
@ -22,18 +22,27 @@ struct location {
static unsigned int test_program; static unsigned int test_program;
static struct location location; static struct location location;
static unsigned int vertex_array_objects[4];
static unsigned int vertex_buffers[4];
static unsigned int vertex_count[4];
//static unsigned int index_buffers[4];
//static unsigned int index_count[4];
static const int vertex_size = 8;
void load_program() void load_program()
{ {
unsigned int program = compile_from_files("shader/test.vert", unsigned int program = compile_from_files("shader/test.vert",
"shader/test.geom",
"shader/test.frag"); "shader/test.frag");
location.attrib.position = glGetAttribLocation(program, "Position"); location.attrib.position = glGetAttribLocation(program, "Position");
location.attrib.normal = glGetAttribLocation(program, "Normal"); location.attrib.block_id = glGetAttribLocation(program, "BlockID");
location.attrib.texture = glGetAttribLocation(program, "Texture"); location.attrib.configuration = glGetAttribLocation(program, "Configuration");
printf("attributes:\n position %u\n normal %u\n texture %u\n", printf("attributes:\n position %u\n block_id %u\n configuration %u\n",
location.attrib.position, location.attrib.position,
location.attrib.normal, location.attrib.block_id,
location.attrib.texture); location.attrib.configuration);
location.uniform.transform = glGetUniformLocation(program, "Transform"); location.uniform.transform = glGetUniformLocation(program, "Transform");
location.uniform.terrain_sampler = glGetUniformLocation(program, "TerrainSampler"); location.uniform.terrain_sampler = glGetUniformLocation(program, "TerrainSampler");
@ -44,23 +53,11 @@ void load_program()
test_program = program; test_program = program;
} }
static unsigned int vertex_array_objects[4];
static unsigned int vertex_buffers[4];
static unsigned int index_buffers[4];
static unsigned int index_count[4];
const char * vertex_paths[] = { const char * vertex_paths[] = {
"minecraft/region.0.0.vtx", "minecraft/region.0.0.inst.vtx",
"minecraft/region.0.-1.vtx", "minecraft/region.0.-1.inst.vtx",
"minecraft/region.-1.0.vtx", "minecraft/region.-1.0.inst.vtx",
"minecraft/region.-1.-1.vtx", "minecraft/region.-1.-1.inst.vtx",
};
static const char * index_paths[] = {
"minecraft/region.0.0.idx",
"minecraft/region.0.-1.idx",
"minecraft/region.-1.0.idx",
"minecraft/region.-1.-1.idx",
}; };
void load_vertex_buffer(int i) void load_vertex_buffer(int i)
@ -70,10 +67,12 @@ void load_vertex_buffer(int i)
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers[i]); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers[i]);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW); 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); free(vertex_buffer_data);
} }
/*
void load_element_buffer(int i) void load_element_buffer(int i)
{ {
int index_buffer_data_size; int index_buffer_data_size;
@ -85,45 +84,49 @@ void load_element_buffer(int i)
free(index_buffer_data); free(index_buffer_data);
} }
*/
void load_vertex_attributes() void load_vertex_attributes()
{ {
glVertexAttribPointer(location.attrib.position, glVertexAttribPointer(location.attrib.position,
3, 3,
GL_FLOAT, GL_SHORT,
GL_FALSE, GL_FALSE,
(sizeof (float)) * 9, vertex_size,
(void*)(0 * 4) (void*)(0)
); );
glVertexAttribPointer(location.attrib.normal, glVertexAttribPointer(location.attrib.block_id,
3, 1,
GL_FLOAT, GL_UNSIGNED_BYTE,
GL_FALSE, GL_FALSE,
(sizeof (float)) * 9, vertex_size,
(void*)(3 * 4) (void*)(6)
); );
glVertexAttribPointer(location.attrib.texture, glVertexAttribPointer(location.attrib.configuration,
3, 1,
GL_FLOAT, GL_UNSIGNED_BYTE,
GL_FALSE, GL_FALSE,
(sizeof (float)) * 9, vertex_size,
(void*)(6 * 4) (void*)(7)
); );
glEnableVertexAttribArray(location.attrib.position); glEnableVertexAttribArray(location.attrib.position);
glEnableVertexAttribArray(location.attrib.normal); glEnableVertexAttribArray(location.attrib.block_id);
glEnableVertexAttribArray(location.attrib.texture); glEnableVertexAttribArray(location.attrib.configuration);
glVertexAttribDivisor(location.attrib.position, 1);
glVertexAttribDivisor(location.attrib.block_id, 1);
glVertexAttribDivisor(location.attrib.configuration, 1);
} }
void load_buffers() void load_buffers()
{ {
glGenVertexArrays(4, vertex_array_objects); glGenVertexArrays(4, vertex_array_objects);
glGenBuffers(4, index_buffers); //glGenBuffers(4, index_buffers);
glGenBuffers(4, vertex_buffers); glGenBuffers(4, vertex_buffers);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
glBindVertexArray(vertex_array_objects[i]); glBindVertexArray(vertex_array_objects[i]);
load_element_buffer(i); //load_element_buffer(i);
load_vertex_buffer(i); load_vertex_buffer(i);
load_vertex_attributes(); load_vertex_attributes();
} }
@ -234,9 +237,22 @@ void draw()
//glBindBuffer(GL_UNIFORM_BUFFER, textures_ubo); //glBindBuffer(GL_UNIFORM_BUFFER, textures_ubo);
//glBindBufferBase(GL_UNIFORM_BUFFER, 0, textures_ubo); //glBindBufferBase(GL_UNIFORM_BUFFER, 0, textures_ubo);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glFrontFace(GL_CCW);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
glBindVertexArray(vertex_array_objects[i]); glBindVertexArray(vertex_array_objects[i]);
glDrawElements(GL_TRIANGLES, index_count[i], GL_UNSIGNED_INT, 0); //glDrawElements(GL_TRIANGLES, index_count[i], GL_UNSIGNED_INT, 0);
int instance_count = vertex_count[i];
//printf("instance_count %d\n", instance_count);
glPointSize(10.0);
glDrawArraysInstanced(GL_POINTS,
0,
1,
instance_count);
} }
} }