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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
local CHUNK_SIZE = require"common.constants".CHUNK_SIZE
local coords = require"common.coords"
local tau = 2*math.pi
-- funny hexagon
local vertices = {}
-- v[1] {0,0}, fill
-- v[2-7] edge, fill
-- v[8-13] inner, outline
-- v[14-19] outer, outline
local map = {}
do
local function ix(n) return n%6 end
local function th(n) return tau*(ix(n)+0.5)/6 end
local cos,sin = math.cos,math.sin
local OLWIDTH = 0.11
local hw = OLWIDTH/2
local ri,ro = 1-hw,1+hw
local function ve(n,f) return {cos(th(n)),sin(th(n)), f} end
local function vi(n,f) return {ri*cos(th(n)),ri*sin(th(n)), f} end
local function vo(n,f) return {ro*cos(th(n)),ro*sin(th(n)), f} end
local function apv(...) for _,x in ipairs({...}) do table.insert(vertices,x) end end
local function apm(...) for _,x in ipairs({...}) do table.insert(map,x) end end
vertices[1] = {0,0, 1}
for n=0,5 do apv(ve(n,1)) end
for n=0,5 do apv(vi(n,0)) end
for n=0,5 do apv(vo(n,0)) end
-- fill area
for n=0,5 do apm(1, 2+n, 2+ix(1+n) ) end
local function ii(n) return 8+ix(n) end
local function oi(n) return 14+ix(n) end
-- outline area
for n=0,5 do
apm( ii(n), oi(n), oi(n+1) )
apm( ii(n), oi(n+1), ii(n+1) )
end
end
local shape_mesh = love.graphics.newMesh({
{"VertexPosition","float",2},
{"fillness","float",1},
},vertices,"triangles","static")
shape_mesh:setVertexMap(map)
local function c(...) return {love.math.colorFromBytes(...)} end
-- taken from breadquest
local colors = {
{0,0,0},
c(255,64,64), -- red
c(255,128,0), -- orange
c(192,192,64), -- yellow
c(0,192,0), -- green
c(0,192,192), -- teal
c(64,64,255), -- blue
c(192,0,192), -- purple
c(128,128,128), -- grey
c(0xe7,0x9e,0), -- ubqorange
}
local shader = love.graphics.newShader([[
#pragma language glsl3
const mat2 hex_to_pos = mat2( sqrt(3), 0, sqrt(3)/2, 1.5);
#define CHUNK_SIZE ]]..tostring(CHUNK_SIZE)..[[.0
uniform vec3 colors[10];
uniform float zoom;
attribute float tile_type;
attribute float fillness;
varying vec4 tcol;
const float zthr0 = 2.7;
const float zthr1 = 6;
const float zthrd = zthr1-zthr0;
vec4 position(mat4 transform_projection, vec4 vertex_position)
{
vec2 instance_pos = vec2( floor(love_InstanceID/CHUNK_SIZE), mod(love_InstanceID, CHUNK_SIZE) );
vertex_position.xy += hex_to_pos * instance_pos;
float a = clamp( (zoom-zthr0)/zthrd, 0, 1);
a = max(fillness, a);
int tidx = int(tile_type);
tcol = (tidx == 0) ? vec4(0.0) : vec4(fillness*colors[tidx], a);
return transform_projection * vertex_position;
}
]],[[
#pragma language glsl3
varying vec4 tcol;
vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords)
{
// return vec4(tcol.xyz,0.5);
return tcol;
}
]])
shader:send("colors",unpack(colors))
local function set_imesh(im)
shape_mesh:detachAttribute("tile_type")
shape_mesh:attachAttribute("tile_type",im,"perinstance")
end
local function draw_map(camera,map)
shader:send("zoom",camera.zoom)
love.graphics.setShader(shader)
local cam_tl,cam_br = camera:extents()
local count = CHUNK_SIZE*CHUNK_SIZE
for _,ch in map:iter_chunks() do
if ch then
-- todo: skip chunks that aren't on screen, maybe
local htl,hbr = ch.cp:extents()
local tl = htl:to_pos()
local br = hbr:to_pos()
if br.x < cam_tl.x or cam_br.x < tl.x or br.y < cam_tl.y or cam_br.y < tl.y then
-- definitely not visible on screen
-- this does not catch every single nonvisible chunk
goto next
end
set_imesh(ch.imesh)
love.graphics.drawInstanced(shape_mesh, count, tl.x, tl.y)
end
::next::
end
love.graphics.setShader()
end
return {draw_map=draw_map}
|