From d092f5d89c0fda5cc67349d5489b4ef1b294e053 Mon Sep 17 00:00:00 2001 From: Ilion Beyst Date: Mon, 18 Jul 2022 21:02:27 +0200 Subject: [PATCH] use texture for rendering ships --- web/pw-visualizer/assets/res/ship.png | Bin 0 -> 4963 bytes web/pw-visualizer/assets/res/ship.svg | 51 +++++++------ web/pw-visualizer/src/assets.ts | 1 + web/pw-visualizer/src/index.ts | 100 +++++++++++++------------ web/pw-visualizer/src/webgl/text.ts | 8 +- web/pw-visualizer/src/webgl/texture.ts | 24 +++--- 6 files changed, 96 insertions(+), 88 deletions(-) create mode 100644 web/pw-visualizer/assets/res/ship.png diff --git a/web/pw-visualizer/assets/res/ship.png b/web/pw-visualizer/assets/res/ship.png new file mode 100644 index 0000000000000000000000000000000000000000..fe289aa665f8de494bf67e657fb2b5eba0b8fbdd GIT binary patch literal 4963 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 + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + inkscape:window-y="32" + inkscape:window-maximized="1" + gridtolerance="10" + inkscape:pagecheckerboard="0" + units="cm"> + id="grid894" + originx="-160.50747" + originy="118.75037" /> @@ -53,7 +57,6 @@ image/svg+xml - @@ -61,17 +64,17 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(229.05372,-117.27915)"> + transform="translate(68.546255,1.4712222)"> + style="opacity:1;fill:#00ffff;fill-opacity:1;stroke:none;stroke-width:6.61458;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> diff --git a/web/pw-visualizer/src/assets.ts b/web/pw-visualizer/src/assets.ts index be155c5..5fa5215 100644 --- a/web/pw-visualizer/src/assets.ts +++ b/web/pw-visualizer/src/assets.ts @@ -5,6 +5,7 @@ export {default as marsSvg} from "../assets/res/mars.svg"; export {default as venusSvg} from "../assets/res/venus.svg"; export {default as earthPng} from "../assets/res/earth.png"; +export {default as shipPng} from "../assets/res/ship.png"; export {default as fontPng} from "../assets/res/font.png"; diff --git a/web/pw-visualizer/src/index.ts b/web/pw-visualizer/src/index.ts index 6f2c1b4..bee1bab 100644 --- a/web/pw-visualizer/src/index.ts +++ b/web/pw-visualizer/src/index.ts @@ -1,6 +1,4 @@ import { Game } from "planetwars-rs"; -// import { memory } from "planetwars-rs/planetwars_rs_bg"; -// const memory = planetwars_bg.memory; import type { Dictionary } from './webgl/util'; import type { BBox } from "./voronoi/voronoi-core"; @@ -8,8 +6,6 @@ import { Resizer, resizeCanvasToDisplaySize, FPSCounter, - url_to_mesh, - Mesh, } from "./webgl/util"; import { Shader, @@ -40,14 +36,6 @@ function to_bbox(box: number[]): BBox { }; } -// function f32v(ptr: number, size: number): Float32Array { -// return new Float32Array(memory.buffer, ptr, size); -// } - -// function i32v(ptr: number, size: number): Int32Array { -// return new Int32Array(memory.buffer, ptr, size); -// } - export function set_game_name(name: string) { ELEMENTS["name"].innerHTML = name; } @@ -142,6 +130,7 @@ export class GameInstance { ship_ibo: IndexBuffer; ship_vao: VertexArray; + ship_texture: Texture; // TODO: find a better way max_num_ships: number; @@ -161,8 +150,9 @@ export class GameInstance { constructor( game: Game, - meshes: Mesh[], - ship_mesh: Mesh, + planets_textures: Texture[], + ship_texture: Texture, + font_texture: Texture, shaders: Dictionary ) { this.game = game; @@ -178,10 +168,12 @@ export class GameInstance { }); this.masked_image_shader = shaders["masked_image"].create_shader(GL); - this.text_factory = defaultLabelFactory(GL, this.image_shader); + this.text_factory = defaultLabelFactory(GL, font_texture, this.image_shader); this.planet_labels = []; this.ship_labels = []; + this.ship_texture = ship_texture + this.resizer = new Resizer(CANVAS, [...game.get_viewbox()], true); this.renderer = new Renderer(); this.game.update_turn(0); @@ -191,15 +183,8 @@ export class GameInstance { // List of [(x, y, r)] for all planets this._create_voronoi(planets); - this._create_planets(planets, meshes); + this._create_planets(planets, planets_textures); - // create_shipes - this.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"); - this.ship_vao = new VertexArray(); - this.ship_vao.addBuffer(ship_positions, ship_layout); this.max_num_ships = 0; // Set slider correctly @@ -236,9 +221,7 @@ export class GameInstance { this.renderer.addRenderable(this.vor_builder.getRenderable(), LAYERS.vor); } - _create_planets(planets: Float32Array, meshes: Mesh[]) { - const earth = Texture.fromImage(GL, assets.earthPng, 'earth'); - + _create_planets(planets: Float32Array, planets_textures: Texture[]) { for (let i = 0; i < this.planet_count; i++) { { const transform = new UniformMatrix3fv([ @@ -280,7 +263,7 @@ export class GameInstance { u_trans_next: transform, }; - const renderable = new DefaultRenderable(ib, vao, this.masked_image_shader, [earth], uniforms); + const renderable = new DefaultRenderable(ib, vao, this.masked_image_shader, [planets_textures[0]], uniforms); this.renderer.addRenderable(renderable, LAYERS.planet); @@ -361,16 +344,39 @@ export class GameInstance { const ship_colours = this.game.get_ship_colours(); for (let i = this.max_num_ships; i < ship_counts.length; i++) { - this.renderer.addToDraw( - this.ship_ibo, - this.ship_vao, - this.shader, - {}, - [], - LAYERS.ship - ); + const gl = GL; + const ib = new IndexBuffer(gl, [ + 0, 1, 2, + 1, 2, 3 + ]); + const ratio = this.ship_texture.getWidth() / this.ship_texture.getHeight(); + const vb_pos = new VertexBuffer(gl, [ + -ratio, 1, + ratio, 1, + -ratio, -1, + ratio, -1 + ]); + const vb_tex = new VertexBuffer(gl, [ + 0, 0, + 1, 0, + 0, 1, + 1, 1, + ]); + + const layout_pos = new VertexBufferLayout(); + layout_pos.push(gl.FLOAT, 2, 4, "a_position"); + + const layout_tex = new VertexBufferLayout(); + layout_tex.push(gl.FLOAT, 2, 4, "a_texCoord"); + + const vao = new VertexArray(); + vao.addBuffer(vb_pos, layout_pos); + vao.addBuffer(vb_tex, layout_tex); + const renderable = new DefaultRenderable(ib, vao, this.masked_image_shader, [this.ship_texture], {}); + this.renderer.addRenderable(renderable, LAYERS.ship); const label = this.text_factory.build(GL); + this.ship_labels.push(label); this.renderer.addRenderable(label.getRenderable(), LAYERS.ship_label); } @@ -579,18 +585,17 @@ export class GameInstance { } var game_instance: GameInstance; -var meshes: Mesh[]; +var textures: Texture[]; var shaders: Dictionary; export async function set_instance(source: string): Promise { // TODO: embed shader programs - if (!meshes || !shaders) { - const mesh_promises = [ - assets.shipSvg, - assets.earthSvg, - assets.marsSvg, - assets.venusSvg, - ].map(url_to_mesh); + if (!textures || !shaders) { + const texture_promises = [ + Texture.fromImage(GL, assets.fontPng, "font"), + Texture.fromImage(GL, assets.shipPng, "ship"), + Texture.fromImage(GL, assets.earthPng, "earth") + ]; const shader_promies = [ (async () => @@ -628,8 +633,8 @@ export async function set_instance(source: string): Promise { ]; let shaders_array: [string, ShaderFactory][]; - [meshes, shaders_array] = await Promise.all([ - Promise.all(mesh_promises), + [textures, shaders_array] = await Promise.all([ + Promise.all(texture_promises), Promise.all(shader_promies), ]); @@ -641,8 +646,9 @@ export async function set_instance(source: string): Promise { game_instance = new GameInstance( Game.new(source), - meshes.slice(1), - meshes[0], + textures.slice(2), + textures[1], + textures[0], shaders ); diff --git a/web/pw-visualizer/src/webgl/text.ts b/web/pw-visualizer/src/webgl/text.ts index cb72a42..1ae6f37 100644 --- a/web/pw-visualizer/src/webgl/text.ts +++ b/web/pw-visualizer/src/webgl/text.ts @@ -33,8 +33,8 @@ export class LabelFactory { font: FontInfo; shader: Shader; - constructor(gl: WebGLRenderingContext, loc: string, font: FontInfo, shader: Shader) { - this.texture = Texture.fromImage(gl, loc, 'font'); + constructor(gl: WebGLRenderingContext, fontTexture: Texture, font: FontInfo, shader: Shader) { + this.texture = fontTexture; this.font = font; this.shader = shader; } @@ -144,7 +144,7 @@ export class Label { } } -export function defaultLabelFactory(gl: WebGLRenderingContext, shader: Shader): LabelFactory { +export function defaultLabelFactory(gl: WebGLRenderingContext, fontTexture: Texture, shader: Shader): LabelFactory { const fontInfo = { letterHeight: 8, spaceWidth: 8, @@ -195,5 +195,5 @@ export function defaultLabelFactory(gl: WebGLRenderingContext, shader: Shader): }, }; - return new LabelFactory(gl, fontPng, fontInfo, shader); + return new LabelFactory(gl, fontTexture, fontInfo, shader); } diff --git a/web/pw-visualizer/src/webgl/texture.ts b/web/pw-visualizer/src/webgl/texture.ts index 9d6adcf..faafe76 100644 --- a/web/pw-visualizer/src/webgl/texture.ts +++ b/web/pw-visualizer/src/webgl/texture.ts @@ -11,15 +11,18 @@ export class Texture { gl: WebGLRenderingContext, path: string, name: string, - ): Texture { - const out = new Texture(gl, name); + ): Promise { + return new Promise((resolve, reject) => { + const out = new Texture(gl, name); - const image = new Image(); - image.onload = out.setImage.bind(out, gl, image); - image.onerror = error; - image.src = path; - - return out; + const image = new Image(); + image.onload = () => { + out.setImage(gl, image); + resolve(out); + } + image.onerror = reject; + image.src = path; + }) } static fromRenderer( @@ -99,8 +102,3 @@ export class Texture { return this.height; } } - -function error(e: any) { - console.error("IMAGE LOAD ERROR"); - console.error(e); -}