Flying straight
This commit is contained in:
parent
89eae79eca
commit
adc8759e0e
7 changed files with 404 additions and 77 deletions
|
@ -4,11 +4,12 @@ extern crate serde_derive;
|
|||
extern crate serde_json;
|
||||
extern crate octoon_math;
|
||||
|
||||
use octoon_math::{Mat3, Vec3};
|
||||
use octoon_math::{Mat3, Vec3, One};
|
||||
|
||||
mod utils;
|
||||
mod types;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
||||
|
@ -17,16 +18,128 @@ use wasm_bindgen::prelude::*;
|
|||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Circle {
|
||||
r: f32,
|
||||
x: f32,
|
||||
y: f32,
|
||||
a1: f32,
|
||||
a2: f32,
|
||||
distance: usize,
|
||||
}
|
||||
|
||||
impl Circle {
|
||||
pub fn new(p1: &types::Planet, p2: &types::Planet) -> Self {
|
||||
let dx = p1.x - p2.x;
|
||||
let dy = p1.y - p2.y;
|
||||
let dr = (dx * dx + dy * dy).sqrt();
|
||||
let r = dr * 1.05;
|
||||
let distance = (dx * dx + dy * dy).sqrt().ceil() as usize;
|
||||
|
||||
let d = p1.x * p2.y - p2.x * p1.y;
|
||||
|
||||
let x = (d * dy + dy.signum() * dx * (r * r * dr * dr - d * d).sqrt()) / (dr * dr);
|
||||
let y = (-d * dx + dy.abs() * (r * r * dr * dr - d * d).sqrt()) / (dr * dr);
|
||||
|
||||
let a1 = (y - p1.y).atan2(x - p1.x);
|
||||
let a2 = (y - p2.y).atan2(x - p2.x);
|
||||
|
||||
Self {
|
||||
r, x, y, a1, a2, distance
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_for_remaining(&self, remaining: usize) -> (Mat3<f32>, Mat3<f32>) {
|
||||
(
|
||||
self.get_remaining(remaining),
|
||||
self.get_remaining((remaining + 1).min(self.distance - 1)),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_remaining(&self, remaining: usize) -> Mat3<f32> {
|
||||
let alpha = self.a1 + (1.0 - (remaining as f32 / self.distance as f32)) * (self.a2 - self.a1);
|
||||
let c = alpha.cos();
|
||||
let s = alpha.sin();
|
||||
|
||||
Mat3::new(
|
||||
c, -s, 0.0,
|
||||
s, c, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
) * Mat3::new(
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
self.x, self.y, 1.0,
|
||||
) * Mat3::new(
|
||||
c, -s, 0.0,
|
||||
s, c, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct Line {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
x2: f32,
|
||||
y2: f32,
|
||||
a: f32,
|
||||
d: usize,
|
||||
}
|
||||
impl Line {
|
||||
pub fn new(p1: &types::Planet, p2: &types::Planet) -> Self {
|
||||
let dx = p1.x - p2.x;
|
||||
let dy = p1.y - p2.y;
|
||||
let a = dy.atan2(dx);
|
||||
// let a = (dy / dx).atan();
|
||||
let d = (dx * dx + dy * dy).sqrt().ceil() as usize + 1;
|
||||
|
||||
Self {
|
||||
x1: p1.x,
|
||||
x2: p2.x,
|
||||
y1: p1.y,
|
||||
y2: p2.y,
|
||||
d, a,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_for_remaining(&self, remaining: usize) -> (Mat3<f32>, Mat3<f32>) {
|
||||
(
|
||||
self.get_remaining(remaining),
|
||||
self.get_remaining((remaining + 1).min(self.d - 1)),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_remaining(&self, remaining: usize) -> Mat3<f32> {
|
||||
let x = (self.x1 * remaining as f32 + (self.d - remaining) as f32 * self.x2) / self.d as f32;
|
||||
// let x = self.x1 + (remaining as f32 / self.d as f32) * (self.x2 - self.x1);
|
||||
let y = (self.y1 * remaining as f32 + (self.d - remaining) as f32 * self.y2) / self.d as f32;
|
||||
|
||||
let c = self.a.cos();
|
||||
let s = self.a.sin();
|
||||
// let y = self.y1 + (remaining as f32 / self.d as f32) * (self.y2 - self.y1);
|
||||
Mat3::new(
|
||||
0.3, 0.0, 0.0,
|
||||
0.0, 0.3, 0.0,
|
||||
x, y, 0.3,
|
||||
) * Mat3::rotate_z(self.a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Game {
|
||||
states: Vec<types::State>,
|
||||
turn: usize,
|
||||
|
||||
planet_map: HashMap<(String, String), Line>,
|
||||
|
||||
/* put extra shit here */
|
||||
planets: Vec<Vec3<f32>>,
|
||||
view_box: Vec<f32>,
|
||||
|
||||
ship_locations: Vec<Mat3<f32>>,
|
||||
planets: Vec<Vec3<f32>>,
|
||||
|
||||
ship_locations: Vec<[f32;9]>,
|
||||
ship_colours: Vec<Vec3<f32>>,
|
||||
current_planet_colours: Vec<Vec3<f32>>,
|
||||
}
|
||||
|
||||
|
@ -36,16 +149,32 @@ impl Game {
|
|||
utils::set_panic_hook();
|
||||
|
||||
// First line is fucked but we just filter out things that cannot parse
|
||||
let states: Vec<types::State> = file.split("\n").filter_map(|line|
|
||||
let mut states: Vec<types::State> = file.split("\n").filter_map(|line|
|
||||
serde_json::from_str(line).ok()
|
||||
).collect();
|
||||
states.push(types::State {
|
||||
planets: states.last().unwrap().planets.clone(),
|
||||
expeditions: Vec::new()
|
||||
});
|
||||
|
||||
let mut planet_map = HashMap::new();
|
||||
|
||||
// Iterator?
|
||||
for p1 in states[0].planets.iter() {
|
||||
for p2 in states[0].planets.iter() {
|
||||
planet_map.insert((p1.name.clone(), p2.name.clone()), Line::new(&p1, &p2));
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
planets: utils::get_planets(&states[0].planets, 2.0),
|
||||
view_box: utils::caclulate_viewbox(&states[0].planets),
|
||||
|
||||
planet_map,
|
||||
turn: 0,
|
||||
states,
|
||||
ship_locations: Vec::new(),
|
||||
ship_colours: Vec::new(),
|
||||
current_planet_colours: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +224,17 @@ impl Game {
|
|||
}
|
||||
|
||||
fn update_ship_locations(&mut self) {
|
||||
let mut new_vec = Vec::new();
|
||||
for ship in self.states[self.turn].expeditions.iter() {
|
||||
let (o1, o2) = self.planet_map.get(&(ship.origin.clone(), ship.destination.clone())).unwrap().get_for_remaining(ship.turns_remaining as usize);
|
||||
new_vec.push(o1.to_array());
|
||||
new_vec.push(o2.to_array());
|
||||
}
|
||||
self.ship_locations = new_vec;
|
||||
|
||||
self.ship_colours = self.states[self.turn].expeditions.iter().map(|s| {
|
||||
utils::COLORS[s.owner as usize % utils::COLORS.len()].into()
|
||||
}).collect();
|
||||
}
|
||||
|
||||
// pub fn add_location(&mut self, x: f32, y: f32, angle: f32) {
|
||||
|
@ -104,13 +243,21 @@ impl Game {
|
|||
// );
|
||||
// }
|
||||
|
||||
pub fn location_count(&self) -> usize {
|
||||
self.ship_locations.len()
|
||||
pub fn get_max_ships(&self) -> usize {
|
||||
self.states.iter().map(|s| s.expeditions.len()).max().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_ship_locations(&self) -> *const Mat3<f32> {
|
||||
pub fn get_ship_count(&self) -> usize {
|
||||
self.states[self.turn].expeditions.len()
|
||||
}
|
||||
|
||||
pub fn get_ship_locations(&self) -> *const [f32;9] {
|
||||
self.ship_locations.as_ptr()
|
||||
}
|
||||
|
||||
pub fn get_ship_colours(&self) -> *const Vec3<f32> {
|
||||
self.ship_colours.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,26 @@ pub struct Planet {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
|
||||
impl Hash for Planet {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
unsafe {
|
||||
let x: u32 = mem::transmute_copy(&self.x);
|
||||
let y: u32 = mem::transmute_copy(&self.y);
|
||||
state.write_u32(x);
|
||||
state.write_u32(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Planet {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
(self.x - other.x).abs() < 0.0001 && (self.y - other.y).abs() < 0.0001
|
||||
}
|
||||
}
|
||||
impl Eq for Planet {}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct State {
|
||||
|
|
|
@ -50,6 +50,8 @@ ShaderFactory.create_factory(
|
|||
LOCATION + "static/shaders/frag/simple.glsl", LOCATION + "static/shaders/vert/simple.glsl"
|
||||
).then((e) => SHADERFACOTRY = e);
|
||||
|
||||
|
||||
|
||||
class GameInstance {
|
||||
resizer: Resizer;
|
||||
game: Game;
|
||||
|
@ -60,7 +62,9 @@ class GameInstance {
|
|||
last_time = 0;
|
||||
frame = -1;
|
||||
|
||||
constructor(game: Game, meshes: Mesh[]) {
|
||||
ship_indices: number[];
|
||||
|
||||
constructor(game: Game, meshes: Mesh[], ship_mesh: Mesh) {
|
||||
this.game = game;
|
||||
this.planet_count = this.game.get_planet_count();
|
||||
this.shader = SHADERFACOTRY.create_shader(GL, {"MAX_CIRCLES": ''+this.planet_count});
|
||||
|
@ -93,18 +97,36 @@ class GameInstance {
|
|||
this.shader,
|
||||
{
|
||||
"u_trans": transform,
|
||||
"u_trans_next": transform,
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// this.game.update_turn(this.frame);
|
||||
this.ship_indices = [];
|
||||
const ship_ibo = new IndexBuffer(GL, ship_mesh.cells);
|
||||
const ship_positions = new VertexBuffer(GL, ship_mesh.positions);
|
||||
const ship_layout = new VertexBufferLayout();
|
||||
ship_layout.push(GL.FLOAT, 3, 4, "a_position");
|
||||
const ship_vao = new VertexArray();
|
||||
ship_vao.addBuffer(ship_positions, ship_layout);
|
||||
|
||||
console.log(f32v(this.game.get_planet_colors(), 3 * this.game.get_planet_count()));
|
||||
// console.log(this.resizer.get_viewbox());
|
||||
for (let i = 0; i < this.game.get_max_ships(); i++) {
|
||||
this.ship_indices.push(
|
||||
this.renderer.addToDraw(
|
||||
ship_ibo,
|
||||
ship_vao,
|
||||
this.shader,
|
||||
{}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render(time: number) {
|
||||
if (time > this.last_time + 1000) {
|
||||
if (time > this.last_time + 500) {
|
||||
const transparant = new Uniform3f(0, 0, 0);
|
||||
const transform = new UniformMatrix3fv([0, 0, 0, 0, 0, 0, 0, 0, 0, ]);
|
||||
|
||||
this.last_time = time;
|
||||
this.frame ++;
|
||||
this.game.update_turn(this.frame);
|
||||
|
@ -117,13 +139,40 @@ class GameInstance {
|
|||
this.renderer.updateUniform(i, (us) => us["u_color_next"] = u2);
|
||||
}
|
||||
|
||||
const ships = f32v(this.game.get_ship_locations(), this.game.get_ship_count() * 9 * 2);
|
||||
const ship_colours = f32v(this.game.get_ship_colours(), this.game.get_ship_count() * 3);
|
||||
|
||||
for (let i=0; i < this.game.get_max_ships(); i++) {
|
||||
const index = this.ship_indices[i];
|
||||
if (i < this.game.get_ship_count()) {
|
||||
|
||||
this.renderer.enableRendershit(index);
|
||||
|
||||
const u = new Uniform3f(ship_colours[i*3], ship_colours[i*3 + 1], ship_colours[i*3 + 2]);
|
||||
// const t1 = new UniformMatrix3fv(new Float32Array(ships, i * 18, 9));
|
||||
// const t2 = new UniformMatrix3fv(new Float32Array(ships, i * 18 + 9, 9));
|
||||
|
||||
const t1 = new UniformMatrix3fv(ships.slice(i * 18, i * 18 + 9));
|
||||
const t2 = new UniformMatrix3fv(ships.slice(i * 18 + 9, i * 18 + 18));
|
||||
|
||||
this.renderer.updateUniform(index, (us) => {
|
||||
us["u_color"] = u;
|
||||
us["u_color_next"] = u;
|
||||
us["u_trans"] = t1;
|
||||
us["u_trans_next"] = t2;
|
||||
});
|
||||
} else {
|
||||
this.renderer.disableRenderShift(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL.bindFramebuffer(GL.FRAMEBUFFER, null);
|
||||
GL.viewport(0, 0, GL.canvas.width, GL.canvas.height);
|
||||
GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
|
||||
|
||||
this.shader.uniform(GL, "u_step_interval", new Uniform1f(1000));
|
||||
this.shader.uniform(GL, "u_time", new Uniform1f(time));
|
||||
this.shader.uniform(GL, "u_step_interval", new Uniform1f(500));
|
||||
this.shader.uniform(GL, "u_time", new Uniform1f((time - this.last_time) / 500));
|
||||
this.shader.uniform(GL, "u_mouse", new Uniform2f(this.resizer.get_mouse_pos()));
|
||||
this.shader.uniform(GL, "u_viewbox", new Uniform4f(this.resizer.get_viewbox()));
|
||||
this.shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
||||
|
@ -138,18 +187,18 @@ var game_instance: GameInstance;
|
|||
|
||||
export async function set_instance(game: Game) {
|
||||
const meshes = await Promise.all(
|
||||
["earth.svg", "mars.svg", "venus.svg"].map(
|
||||
["ship.svg", "earth.svg", "mars.svg", "venus.svg"].map(
|
||||
(name) => "static/res/assets/" + name
|
||||
).map(url_to_mesh)
|
||||
);
|
||||
game_instance = new GameInstance(game, meshes);
|
||||
game_instance = new GameInstance(game, meshes.slice(1), meshes[0]);
|
||||
}
|
||||
|
||||
|
||||
function step(time: number) {
|
||||
if (game_instance) {
|
||||
game_instance.render(time);
|
||||
set_loading(false);
|
||||
game_instance.render(time);
|
||||
} else {
|
||||
set_loading(true);
|
||||
}
|
||||
|
|
66
frontend/www/static/res/assets/ship.svg
Normal file
66
frontend/www/static/res/assets/ship.svg
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 99.999999"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="ship.svg"
|
||||
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.24748737"
|
||||
inkscape:cx="-106.07564"
|
||||
inkscape:cy="608.26605"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1012"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(229.05372,-117.27915)">
|
||||
<path
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.72543406;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -229.05372,167.27915 c 0,0 13.45401,-50 48.27481,-50 11.57339,0 21.79319,8.51775 27.92829,21.52314 7.7319,-15.5144 21.11806,-16.32589 22.56968,-13.92304 1.75107,2.89851 1.72384,19.14347 -0.70314,25.00722 -1.17787,2.84584 -10.35261,5.01798 -16.67359,6.19846 0.55938,3.59896 0.85565,7.34571 0.85565,11.19422 0,3.84851 -0.29627,7.59526 -0.85565,11.19423 6.32098,1.18047 15.49572,3.35262 16.67359,6.19845 2.42698,5.86375 2.45421,22.10872 0.70314,25.00723 -1.45162,2.40285 -14.83778,1.59135 -22.56968,-13.92304 -6.1351,13.00539 -16.3549,21.52313 -27.92829,21.52313 -34.8208,0 -48.27481,-50 -48.27481,-50 z m 24.32378,0 a 25.255825,28.025483 0 0 0 25.25579,28.02559 25.255825,28.025483 0 0 0 25.25578,-28.02559 25.255825,28.025483 0 0 0 -25.25578,-28.02558 25.255825,28.025483 0 0 0 -25.25579,28.02558 z"
|
||||
id="path815"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -4,16 +4,24 @@ precision mediump float;
|
|||
|
||||
attribute vec2 a_position;
|
||||
|
||||
|
||||
uniform float u_step_interval;
|
||||
uniform float u_time;
|
||||
|
||||
uniform vec4 u_viewbox; // [x, y, width, height]
|
||||
uniform vec2 u_resolution;
|
||||
uniform mat3 u_trans;
|
||||
uniform mat3 u_trans_next;
|
||||
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
vec3 pos = vec3(a_position, 1.0);
|
||||
|
||||
pos = u_trans * pos;
|
||||
// float part = fract(u_time / u_step_interval);
|
||||
mat3 trans = (u_trans_next * (1.0 - u_time)) + (u_trans * u_time);
|
||||
|
||||
pos = trans * pos;
|
||||
|
||||
vec2 uv = pos.xy;
|
||||
|
||||
|
|
|
@ -9,41 +9,109 @@ export interface Renderable {
|
|||
render(gl: WebGLRenderingContext): void;
|
||||
}
|
||||
|
||||
export class Renderer {
|
||||
renderables: Renderable[];
|
||||
|
||||
indexBuffers: IndexBuffer[];
|
||||
vertexArrays: VertexArray[];
|
||||
shaders: Shader[];
|
||||
class RenderShit implements Renderable {
|
||||
ibo: IndexBuffer;
|
||||
va: VertexArray;
|
||||
shader: Shader;
|
||||
textures: Texture[];
|
||||
uniforms: Dictionary<Uniform>[];
|
||||
uniforms: Dictionary<Uniform>;
|
||||
|
||||
enabled: boolean;
|
||||
|
||||
constructor(
|
||||
ibo: IndexBuffer,
|
||||
va: VertexArray,
|
||||
shader: Shader,
|
||||
textures: Texture[],
|
||||
uniforms: Dictionary<Uniform>,
|
||||
) {
|
||||
this.enabled = true;
|
||||
this.ibo = ibo;
|
||||
this.va = va;
|
||||
this.shader = shader;
|
||||
this.textures = textures;
|
||||
this.uniforms = uniforms;
|
||||
}
|
||||
|
||||
render(gl: WebGLRenderingContext): void {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const indexBuffer = this.ibo;
|
||||
const vertexArray = this.va;
|
||||
const uniforms = this.uniforms;
|
||||
|
||||
const shader = this.shader;
|
||||
const textures = this.textures;
|
||||
let texLocation = 0;
|
||||
|
||||
for (let texture of textures) {
|
||||
|
||||
shader.uniform(gl, texture.name, new Uniform1i(texLocation));
|
||||
texture.bind(gl, texLocation);
|
||||
|
||||
texLocation ++;
|
||||
// if (texLocation > maxTextures) {
|
||||
// console.error("Using too many textures, this is not supported yet\nUndefined behaviour!");
|
||||
// }
|
||||
}
|
||||
|
||||
if (vertexArray && shader && uniforms) {
|
||||
for(let key in uniforms) {
|
||||
shader.uniform(gl, key, uniforms[key]);
|
||||
}
|
||||
|
||||
vertexArray.bind(gl, shader);
|
||||
|
||||
if (indexBuffer) {
|
||||
indexBuffer.bind(gl);
|
||||
gl.drawElements(gl.TRIANGLES, indexBuffer.getCount(), gl.UNSIGNED_SHORT, 0);
|
||||
} else {
|
||||
console.error("IndexBuffer is required to render, for now");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class Renderer {
|
||||
renderables: RenderShit[];
|
||||
|
||||
constructor() {
|
||||
this.indexBuffers = [];
|
||||
this.vertexArrays = [];
|
||||
this.shaders = [];
|
||||
this.textures = [];
|
||||
this.uniforms = [];
|
||||
this.renderables = [];
|
||||
}
|
||||
|
||||
updateUniform(i: number, f: (uniforms: Dictionary<Uniform>) => void) {
|
||||
f(this.uniforms[i]);
|
||||
f(this.renderables[i].uniforms);
|
||||
}
|
||||
|
||||
addRenderable(item: Renderable) {
|
||||
this.renderables.push(item);
|
||||
disableRenderShift(i: number) {
|
||||
this.renderables[i].enabled = false;
|
||||
}
|
||||
|
||||
addToDraw(indexBuffer: IndexBuffer, vertexArray: VertexArray, shader: Shader, uniforms: Dictionary<Uniform>,texture?: Texture): number {
|
||||
this.indexBuffers.push(indexBuffer);
|
||||
this.vertexArrays.push(vertexArray);
|
||||
this.shaders.push(shader);
|
||||
this.textures.push(texture);
|
||||
enableRendershit(i: number) {
|
||||
this.renderables[i].enabled = true;
|
||||
}
|
||||
|
||||
this.uniforms.push(uniforms);
|
||||
// addRenderable(item: Renderable) {
|
||||
// this.renderables.push(item);
|
||||
// }
|
||||
|
||||
addToDraw(indexBuffer: IndexBuffer, vertexArray: VertexArray, shader: Shader, uniforms?: Dictionary<Uniform>, texture?: Texture[]): number {
|
||||
|
||||
return this.indexBuffers.length - 1;
|
||||
this.renderables.push(
|
||||
new RenderShit(
|
||||
indexBuffer,
|
||||
vertexArray,
|
||||
shader,
|
||||
texture || [],
|
||||
uniforms || {},
|
||||
)
|
||||
);
|
||||
|
||||
return this.renderables.length - 1;
|
||||
}
|
||||
|
||||
render(gl: WebGLRenderingContext, frameBuffer?: WebGLFramebuffer, width?: number, height?: number) {
|
||||
|
@ -52,41 +120,10 @@ export class Renderer {
|
|||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
const maxTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
|
||||
let texLocation = 0;
|
||||
|
||||
for(let i = 0; i < this.indexBuffers.length; i ++) {
|
||||
const indexBuffer = this.indexBuffers[i];
|
||||
const vertexArray = this.vertexArrays[i];
|
||||
const uniforms = this.uniforms[i];
|
||||
|
||||
const shader = this.shaders[i];
|
||||
const texture = this.textures[i];
|
||||
|
||||
if (texture) {
|
||||
|
||||
shader.uniform(gl, texture.name, new Uniform1i(texLocation));
|
||||
texture.bind(gl, texLocation);
|
||||
|
||||
texLocation ++;
|
||||
if (texLocation > maxTextures) {
|
||||
console.error("Using too many textures, this is not supported yet\nUndefined behaviour!");
|
||||
}
|
||||
}
|
||||
|
||||
if (vertexArray && shader && uniforms) {
|
||||
for(let key in uniforms) {
|
||||
shader.uniform(gl, key, uniforms[key]);
|
||||
}
|
||||
|
||||
vertexArray.bind(gl, shader);
|
||||
|
||||
if (indexBuffer) {
|
||||
indexBuffer.bind(gl);
|
||||
gl.drawElements(gl.TRIANGLES, indexBuffer.getCount(), gl.UNSIGNED_SHORT, 0);
|
||||
} else {
|
||||
console.error("IndexBuffer is required to render, for now");
|
||||
}
|
||||
}
|
||||
for (let r of this.renderables) {
|
||||
r.render(gl);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -306,8 +306,8 @@ export class Uniform4f implements Uniform {
|
|||
}
|
||||
|
||||
export class UniformMatrix3fv implements Uniform {
|
||||
data: number[];
|
||||
constructor(data: number[]) {
|
||||
data: number[] | Float32Array;
|
||||
constructor(data: number[] | Float32Array) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue