93 Some(PIXEL_SHADER), |
87 Some(PIXEL_SHADER), |
94 &[ |
88 &[ |
95 VariableBinding::Attribute("Position", 0), |
89 VariableBinding::Attribute("Position", 0), |
96 VariableBinding::Attribute("Uv", 1), |
90 VariableBinding::Attribute("Uv", 1), |
97 VariableBinding::Sampler("Texture", 0), |
91 VariableBinding::Sampler("Texture", 0), |
98 ] |
92 ], |
99 ).unwrap(); |
93 ) |
|
94 .unwrap(); |
100 |
95 |
101 let tile_layout = InputLayout::new(vec![ |
96 let tile_layout = InputLayout::new(vec![ |
102 // position |
97 // position |
103 InputElement { |
98 InputElement { |
104 shader_slot: 0, |
99 shader_slot: 0, |
105 buffer_slot: 0, |
100 buffer_slot: 0, |
106 format: InputFormat::Float(gl::FLOAT, false), |
101 format: InputFormat::Float(gl::FLOAT, false), |
107 components: 2, |
102 components: 2, |
108 stride: 20, |
103 stride: 20, |
109 offset: 0 |
104 offset: 0, |
110 }, |
105 }, |
111 // uv |
106 // uv |
112 InputElement { |
107 InputElement { |
113 shader_slot: 1, |
108 shader_slot: 1, |
114 buffer_slot: 0, |
109 buffer_slot: 0, |
115 format: InputFormat::Float(gl::FLOAT, false), |
110 format: InputFormat::Float(gl::FLOAT, false), |
116 components: 3, |
111 components: 3, |
117 stride: 20, |
112 stride: 20, |
118 offset: 8 |
113 offset: 8, |
119 }, |
114 }, |
120 ]); |
115 ]); |
121 |
116 |
122 MapRenderer { |
117 MapRenderer { |
123 tiles: Vec::new(), |
118 tiles: Vec::new(), |
124 textures: Vec::new(), |
119 textures: Vec::new(), |
125 |
120 |
126 tile_vertex_buffer: Buffer::empty(gl::ARRAY_BUFFER, gl::DYNAMIC_DRAW), |
121 tile_vertex_buffer: Buffer::empty(gl::ARRAY_BUFFER, gl::DYNAMIC_DRAW), |
127 tile_index_buffer: Buffer::empty(gl::ELEMENT_ARRAY_BUFFER, gl::DYNAMIC_DRAW), |
122 tile_index_buffer: Buffer::empty(gl::ELEMENT_ARRAY_BUFFER, gl::DYNAMIC_DRAW), |
128 tile_vertices: Vec::new(), |
123 tile_vertices: Vec::new(), |
129 tile_indices: Vec::new(), |
124 tile_indices: Vec::new(), |
130 index_offset: 0, |
125 index_offset: 0, |
164 let data = unsafe { &land.as_bytes()[offset..] }; |
159 let data = unsafe { &land.as_bytes()[offset..] }; |
165 let stride = land.width(); |
160 let stride = land.width(); |
166 |
161 |
167 (data, stride as u32) |
162 (data, stride as u32) |
168 }; |
163 }; |
169 |
164 |
170 let texture_index = if idx >= self.textures.len() { |
165 let texture_index = if idx >= self.textures.len() { |
171 let texture = Texture2D::with_data( |
166 let texture = Texture2D::with_data( |
172 data, |
167 data, |
173 stride, |
168 stride, |
174 self.tile_width, |
169 self.tile_width, |
175 self.tile_height, |
170 self.tile_height, |
176 gl::RGBA8, |
171 gl::RGBA8, |
177 gl::RGBA, |
172 gl::RGBA, |
178 gl::UNSIGNED_BYTE, |
173 gl::UNSIGNED_BYTE, |
179 gl::NEAREST |
174 gl::NEAREST, |
180 ); |
175 ); |
181 |
176 |
182 let texture_index = self.textures.len(); |
177 let texture_index = self.textures.len(); |
183 self.textures.push(texture); |
178 self.textures.push(texture); |
184 |
179 |
185 texture_index |
180 texture_index |
186 } else { |
181 } else { |
187 let texture_region = Rect::new( |
182 let texture_region = Rect::new( |
188 Point::new(0, 0), |
183 Point::new(0, 0), |
189 Point::new(self.tile_width as i32, self.tile_height as i32) |
184 Point::new(self.tile_width as i32, self.tile_height as i32), |
190 ); |
185 ); |
191 |
186 |
192 self.textures[idx].update(texture_region, data, stride, gl::RGBA, gl::UNSIGNED_BYTE); |
187 self.textures[idx].update( |
|
188 texture_region, |
|
189 data, |
|
190 stride, |
|
191 gl::RGBA, |
|
192 gl::UNSIGNED_BYTE, |
|
193 ); |
193 idx |
194 idx |
194 }; |
195 }; |
195 |
196 |
196 let tile = MapTile { |
197 let tile = MapTile { |
197 texture_index: texture_index as u32, |
198 texture_index: texture_index as u32, |
198 |
199 |
199 // TODO: are there ever non-power of two textures? |
200 // TODO: are there ever non-power of two textures? |
200 width: self.tile_width, |
201 width: self.tile_width, |
201 height: self.tile_height, |
202 height: self.tile_height, |
202 }; |
203 }; |
203 self.tiles.push(tile); |
204 self.tiles.push(tile); |
204 } |
205 } |
205 } |
206 } |
206 } |
207 } |
207 |
208 |
208 pub fn update(&mut self, land: &Land2D<u32>, region: Rect) { |
209 pub fn update(&mut self, land: &Land2D<u32>, region: Rect) {} |
209 |
|
210 } |
|
211 |
210 |
212 pub fn render(&mut self, viewport: Rect) { |
211 pub fn render(&mut self, viewport: Rect) { |
213 self.tile_vertices.clear(); |
212 self.tile_vertices.clear(); |
214 self.tile_indices.clear(); |
213 self.tile_indices.clear(); |
215 self.tile_draw_calls.clear(); |
214 self.tile_draw_calls.clear(); |
216 self.index_offset = 0; |
215 self.index_offset = 0; |
217 |
216 |
218 for (idx, tile) in self.tiles.iter().enumerate() { |
217 for (idx, tile) in self.tiles.iter().enumerate() { |
219 let tile_x = idx as i32 % self.num_tile_x; |
218 let tile_x = idx as i32 % self.num_tile_x; |
220 let tile_y = idx as i32 / self.num_tile_x; |
219 let tile_y = idx as i32 / self.num_tile_x; |
221 let tile_w = self.tile_width as i32; |
220 let tile_w = self.tile_width as i32; |
222 let tile_h = self.tile_height as i32; |
221 let tile_h = self.tile_height as i32; |
232 let tile_w = tile_x + tile_w as f32; |
231 let tile_w = tile_x + tile_w as f32; |
233 let tile_h = tile_y + tile_h as f32; |
232 let tile_h = tile_y + tile_h as f32; |
234 let uv_depth = tile.texture_index as f32; |
233 let uv_depth = tile.texture_index as f32; |
235 |
234 |
236 //dbg!(tile_x); |
235 //dbg!(tile_x); |
237 let tl = TileVertex { pos: [tile_x, tile_y], uv: [0f32, 0f32, uv_depth] }; |
236 let tl = TileVertex { |
238 let bl = TileVertex { pos: [tile_x, tile_h], uv: [0f32, 1f32, uv_depth] }; |
237 pos: [tile_x, tile_y], |
239 let br = TileVertex { pos: [tile_w, tile_h], uv: [1f32, 1f32, uv_depth] }; |
238 uv: [0f32, 0f32, uv_depth], |
240 let tr = TileVertex { pos: [tile_w, tile_y], uv: [1f32, 0f32, uv_depth] }; |
239 }; |
|
240 let bl = TileVertex { |
|
241 pos: [tile_x, tile_h], |
|
242 uv: [0f32, 1f32, uv_depth], |
|
243 }; |
|
244 let br = TileVertex { |
|
245 pos: [tile_w, tile_h], |
|
246 uv: [1f32, 1f32, uv_depth], |
|
247 }; |
|
248 let tr = TileVertex { |
|
249 pos: [tile_w, tile_y], |
|
250 uv: [1f32, 0f32, uv_depth], |
|
251 }; |
241 |
252 |
242 self.tile_vertices.extend(&[tl, bl, br, tr]); |
253 self.tile_vertices.extend(&[tl, bl, br, tr]); |
243 |
254 |
244 let i = self.index_offset; |
255 let i = self.index_offset; |
245 self.tile_indices.extend(&[ |
256 self.tile_indices |
246 i + 0, i + 1, i + 2, |
257 .extend(&[i + 0, i + 1, i + 2, i + 2, i + 3, i + 0]); |
247 i + 2, i + 3, i + 0, |
|
248 ]); |
|
249 self.index_offset += 4; |
258 self.index_offset += 4; |
250 |
259 |
251 self.tile_draw_calls.push(DrawTile { |
260 self.tile_draw_calls.push(DrawTile { |
252 texture_index: tile.texture_index, |
261 texture_index: tile.texture_index, |
253 index_len: 6 |
262 index_len: 6, |
254 }); |
263 }); |
255 } |
264 } |
256 } |
265 } |
257 |
266 |
258 self.tile_vertex_buffer.write_typed(&self.tile_vertices); |
267 self.tile_vertex_buffer.write_typed(&self.tile_vertices); |
259 self.tile_index_buffer.write_typed(&self.tile_indices); |
268 self.tile_index_buffer.write_typed(&self.tile_indices); |
260 |
269 |
261 let _g = self.tile_layout.bind(&[ |
270 let _g = self.tile_layout.bind( |
262 (0, &self.tile_vertex_buffer) |
271 &[(0, &self.tile_vertex_buffer)], |
263 ], Some(&self.tile_index_buffer)); |
272 Some(&self.tile_index_buffer), |
|
273 ); |
264 |
274 |
265 let ortho = { |
275 let ortho = { |
266 let l = viewport.left() as f32; |
276 let l = viewport.left() as f32; |
267 let r = viewport.right() as f32; |
277 let r = viewport.right() as f32; |
268 let b = viewport.bottom() as f32; |
278 let b = viewport.bottom() as f32; |
269 let t = viewport.top() as f32; |
279 let t = viewport.top() as f32; |
270 |
280 |
271 [ |
281 [ |
272 2f32 / (r - l), 0f32, 0f32, 0f32, |
282 2f32 / (r - l), |
273 0f32, 2f32 / (t - b), 0f32, 0f32, |
283 0f32, |
274 0f32, 0f32, 0.5f32, 0f32, |
284 0f32, |
275 (r + l) / (l - r), (t + b) / (b - t), 0.5f32, 1f32, |
285 0f32, |
|
286 0f32, |
|
287 2f32 / (t - b), |
|
288 0f32, |
|
289 0f32, |
|
290 0f32, |
|
291 0f32, |
|
292 0.5f32, |
|
293 0f32, |
|
294 (r + l) / (l - r), |
|
295 (t + b) / (b - t), |
|
296 0.5f32, |
|
297 1f32, |
276 ] |
298 ] |
277 }; |
299 }; |
278 |
300 |
279 self.tile_shader.bind(); |
301 self.tile_shader.bind(); |
280 self.tile_shader.set_matrix("Projection", ortho.as_ptr()); |
302 self.tile_shader.set_matrix("Projection", ortho.as_ptr()); |
281 |
303 |
282 let mut draw_offset = 0; |
304 let mut draw_offset = 0; |
283 for draw_call in &self.tile_draw_calls { |
305 for draw_call in &self.tile_draw_calls { |
284 unsafe { |
306 unsafe { |
285 self.tile_shader.bind_texture_2d(0, &self.textures[draw_call.texture_index as usize]); |
307 self.tile_shader |
286 |
308 .bind_texture_2d(0, &self.textures[draw_call.texture_index as usize]); |
|
309 |
287 gl::DrawElements( |
310 gl::DrawElements( |
288 gl::TRIANGLES, |
311 gl::TRIANGLES, |
289 draw_call.index_len as i32, |
312 draw_call.index_len as i32, |
290 gl::UNSIGNED_SHORT, |
313 gl::UNSIGNED_SHORT, |
291 draw_offset as *const _ |
314 draw_offset as *const _, |
292 ); |
315 ); |
293 } |
316 } |
294 |
317 |
295 draw_offset += draw_call.index_len * 2; |
318 draw_offset += draw_call.index_len * 2; |
296 } |
319 } |
297 } |
320 } |
298 } |
321 } |
299 |
|
300 |
|