Browse Source

Implemented rendering system for ships

raster
Bergmann89 3 years ago
parent
commit
34794e7a3f
23 changed files with 429 additions and 32 deletions
  1. +36
    -0
      glc/src/vector.rs
  2. +1
    -1
      space-crush-app/resources/shader/planet/frag.glsl
  3. +28
    -0
      space-crush-app/resources/shader/ship/frag.glsl
  4. +3
    -0
      space-crush-app/resources/shader/ship/shared.glsl
  5. +17
    -0
      space-crush-app/resources/shader/ship/vert.glsl
  6. BIN
     
  7. BIN
     
  8. BIN
     
  9. +94
    -1
      space-crush-app/resources/world.json
  10. +2
    -1
      space-crush-app/src/lib.rs
  11. +56
    -4
      space-crush-app/src/main.rs
  12. +1
    -3
      space-crush-app/src/misc/window.rs
  13. +2
    -0
      space-crush-app/src/render/mod.rs
  14. +116
    -0
      space-crush-app/src/render/ships.rs
  15. +1
    -1
      space-crush-app/src/resources/state.rs
  16. +2
    -0
      space-crush-common/src/components/mod.rs
  17. +18
    -0
      space-crush-common/src/components/ship.rs
  18. +6
    -17
      space-crush-common/src/components/velocity.rs
  19. +5
    -1
      space-crush-common/src/dispatcher.rs
  20. +2
    -2
      space-crush-common/src/misc/persistence.rs
  21. +2
    -0
      space-crush-common/src/systems/mod.rs
  22. +36
    -0
      space-crush-common/src/systems/movement.rs
  23. +1
    -1
      space-crush-common/src/systems/process.rs

+ 36
- 0
glc/src/vector.rs View File

@@ -304,6 +304,18 @@ where
}
}

impl<T> Mul<T> for Vector2<T>
where
T: Element,
{
type Output = Self;

#[inline]
fn mul(self, rhs: T) -> Self::Output {
self.multiply(rhs)
}
}

/* Vector3 */

impl<T> Vector3<T>
@@ -403,6 +415,18 @@ where
}
}

impl<T> Mul<T> for Vector3<T>
where
T: Element,
{
type Output = Self;

#[inline]
fn mul(self, rhs: T) -> Self::Output {
self.multiply(rhs)
}
}

/* Vector4 */

impl<T> Vector4<T>
@@ -513,6 +537,18 @@ where
}
}

impl<T> Mul<T> for Vector4<T>
where
T: Element,
{
type Output = Self;

#[inline]
fn mul(self, rhs: T) -> Self::Output {
self.multiply(rhs)
}
}

impl<T> From<(Vector3<T>, T)> for Vector4<T> {
fn from((vec3, w): (Vector3<T>, T)) -> Self {
Self {


+ 1
- 1
space-crush-app/resources/shader/planet/frag.glsl View File

@@ -8,7 +8,7 @@ const GlowArgs GLOW_ARGS = {
/* step0 */ 0.480,
/* step1 */ 0.975,
/* pulseSize0 */ 0.010,
/* pulseSize1 */ 0.025,
/* pulseSize1 */ 0.050,
/* pulseTime */ 2.000,
};



+ 28
- 0
space-crush-app/resources/shader/ship/frag.glsl View File

@@ -0,0 +1,28 @@
#version 450 core

#pragma include ./shared.glsl
#pragma include ../misc/glow.glsl
#pragma include ../misc/global.glsl

const GlowArgs GLOW_ARGS = {
/* step0 */ 0.100,
/* step1 */ 1.900,
/* pulseSize0 */ 0.050,
/* pulseSize1 */ 0.200,
/* pulseTime */ 2.000,
};

in FragmentData fragmentData;

uniform vec4 uGlowColor;
uniform sampler2D uTexture;

out vec4 outColor;

void main() {
float alpha = glow(GLOW_ARGS, fragmentData.texCoords - vec2(0.5), uGlobal.time);
vec4 glow = vec4(uGlowColor.rgb, uGlowColor.a * alpha);
vec4 tex = texture(uTexture, fragmentData.texCoords);

outColor = tex * tex.a + glow * (1.0 - tex.a);
}

+ 3
- 0
space-crush-app/resources/shader/ship/shared.glsl View File

@@ -0,0 +1,3 @@
struct FragmentData {
vec2 texCoords;
};

+ 17
- 0
space-crush-app/resources/shader/ship/vert.glsl View File

@@ -0,0 +1,17 @@
#version 450 core

#pragma include ./shared.glsl
#pragma include ../misc/camera.glsl

const float GLOW_SIZE_FACTOR = 4.00;

in vec3 inPosition;

uniform mat4 uModel;

out FragmentData fragmentData;

void main() {
fragmentData.texCoords = inPosition.xy * GLOW_SIZE_FACTOR + vec2(0.5);
gl_Position = uCamera.projection * uCamera.view * uModel * vec4(inPosition * GLOW_SIZE_FACTOR, 1.0);
}

BIN
View File


BIN
View File


BIN
View File


+ 94
- 1
space-crush-app/resources/world.json View File

@@ -1 +1,94 @@
[{"marker":[0],"components":[{"pos":[0.0,0.0],"size":500.0},{}]}]
[
{
"marker": [
0
],
"components": [
{
"pos": [
0.0,
0.0
],
"size": 500.0
},
null,
{},
null
]
},
{
"marker": [
1
],
"components": [
{
"pos": [
250.0,
250.0
],
"size": 30.0
},
{
"dir": [
-0.70710677,
0.70710677
],
"speed": 0.0
},
null,
{
"type_": "Fighter"
}
]
},
{
"marker": [
2
],
"components": [
{
"pos": [
-250.0,
250.0
],
"size": 30.0
},
{
"dir": [
0.0,
1.0
],
"speed": 0.0
},
null,
{
"type_": "Bomber"
}
]
},
{
"marker": [
3
],
"components": [
{
"pos": [
250.0,
-250.0
],
"size": 30.0
},
{
"dir": [
0.70710677,
0.70710677
],
"speed": 0.0
},
null,
{
"type_": "Transporter"
}
]
}
]

+ 2
- 1
space-crush-app/src/lib.rs View File

@@ -10,7 +10,7 @@ use specs::{Dispatcher, DispatcherBuilder, World};
pub use error::Error;

use misc::{Events, TextManager, Window};
use render::{Debug, Init, Planets};
use render::{Debug, Init, Planets, Ships};
use resources::{Camera, Config, Geometry, State, Uniform};
use systems::StateUpdate;

@@ -39,6 +39,7 @@ impl<'a, 'b> App<'a, 'b> {
.with(StateUpdate::new(world)?, "state_update", &[])
.with_thread_local(Init::new(world)?)
.with_thread_local(Planets::new(world)?)
.with_thread_local(Ships::new(world)?)
.with_thread_local(Debug::new(&text_manager)?)
.build();
dispatcher.setup(world);


+ 56
- 4
space-crush-app/src/main.rs View File

@@ -33,7 +33,9 @@ fn run(vfs: Vfs) -> Result<(), Error> {
let mut common = Dispatcher::new(&mut world);
let mut app = App::new(&mut world)?;

load_world(&mut world, WORLD_FILEPATH)?;
if !load_world(&mut world, WORLD_FILEPATH)? {
create_world(&mut world);
}

while app.is_running() {
world.maintain();
@@ -47,19 +49,69 @@ fn run(vfs: Vfs) -> Result<(), Error> {
Ok(())
}

fn load_world(world: &mut World, path: &str) -> Result<(), Error> {
fn create_world(world: &mut World) {
use glc::vector::Vector2f;
use space_crush_common::{
components::{Planet, Position, Ship, ShipType, Velocity},
misc::{PersistWorld, Persistence},
};
use specs::{saveload::MarkedBuilder, Builder};

world
.create_entity()
.marked::<<PersistWorld as Persistence>::Marker>()
.with(Position {
pos: Vector2f::default(),
size: 500.0,
})
.with(Planet {})
.build();

for i in 0..3 {
let x = if i & 1 == 0 { 1.0 } else { -1.0 };
let y = if i & 2 == 0 { 1.0 } else { -1.0 };

world
.create_entity()
.marked::<<PersistWorld as Persistence>::Marker>()
.with(Position {
pos: Vector2f::new(250.0 * x, 250.0 * y),
size: 100.0,
})
.with(Velocity {
dir: Vector2f::new(i as f32 - 1.0, 1.0).normalize(),
speed: 0.0,
})
.with(Ship {
type_: match i {
0 => ShipType::Fighter,
1 => ShipType::Bomber,
2 => ShipType::Transporter,
_ => unreachable!(),
},
})
.build();
}
}

fn load_world(world: &mut World, path: &str) -> Result<bool, Error> {
use serde_json::de::{Deserializer, IoRead};
use space_crush_common::misc::{PersistWorld, Persistence, WorldHelper};

PersistWorld::setup(world);

let vfs = world.resource::<Vfs>()?;
let mut file = vfs.join(path)?.open_file()?;
let path = vfs.join(path)?;
if !path.exists() {
return Ok(false);
}

let mut file = path.open_file()?;
let mut read = IoRead::new(&mut file);
let mut deserializer = Deserializer::new(&mut read);
world.deserialize(PersistWorld, &mut deserializer)?;

Ok(())
Ok(true)
}

fn save_world(world: &mut World, path: &str) -> Result<(), Error> {


+ 1
- 3
space-crush-app/src/misc/window.rs View File

@@ -7,9 +7,7 @@ use glutin::{
};
use log::{error, info};

use crate::Error;

use super::super::resources::Config;
use crate::{resources::Config, Error};

pub struct Window {
context: ContextWrapper<PossiblyCurrent, GlutinWindow>,


+ 2
- 0
space-crush-app/src/render/mod.rs View File

@@ -1,7 +1,9 @@
mod debug;
mod init;
mod planets;
mod ships;

pub use debug::Debug;
pub use init::Init;
pub use planets::Planets;
pub use ships::Ships;

+ 116
- 0
space-crush-app/src/render/ships.rs View File

@@ -0,0 +1,116 @@
use glc::{
matrix::Matrix4f,
misc::{BindGuard, Bindable},
shader::{Program, Type, Uniform},
texture::Texture,
vector::Vector4f,
};
use log::error;
use space_crush_common::components::{Position, Ship, ShipType, Velocity};
use specs::{prelude::*, ReadExpect, ReadStorage, System, World};

use crate::{
constants::{UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM},
misc::WorldHelper,
resources::Geometry,
Error,
};

pub struct Ships {
program: Program,
texture_fighter: Texture,
texture_bomber: Texture,
texture_transporter: Texture,
model_location: gl::GLint,
}

impl Ships {
pub fn new(world: &World) -> Result<Self, Error> {
let program = world.load_program(vec![
(Type::Vertex, "resources/shader/ship/vert.glsl"),
(Type::Fragment, "resources/shader/ship/frag.glsl"),
])?;

program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?;
program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?;

let glow_color = Vector4f::new(1.0, 1.0, 1.0, 0.02);
let glow_color = Uniform::Vector4f(&glow_color);
let model_location = program.uniform_location("uModel")?;

program.bind();
program.uniform("uTexture", Uniform::Texture(0))?;
program.uniform("uGlowColor", glow_color)?;
program.unbind();

let texture_fighter = world.load_texture("resources/textures/ship_fighter.png")?;
let texture_bomber = world.load_texture("resources/textures/ship_bomber.png")?;
let texture_transporter = world.load_texture("resources/textures/ship_transporter.png")?;

Ok(Self {
program,
texture_fighter,
texture_bomber,
texture_transporter,
model_location,
})
}
}

#[derive(SystemData)]
pub struct ShipsData<'a> {
geometry: ReadExpect<'a, Geometry>,
position: ReadStorage<'a, Position>,
velocity: ReadStorage<'a, Velocity>,
ship: ReadStorage<'a, Ship>,
}

impl<'a> System<'a> for Ships {
type SystemData = ShipsData<'a>;

fn run(&mut self, data: Self::SystemData) {
let ShipsData {
geometry,
position,
velocity,
ship,
} = data;

gl::enable(gl::BLEND);
gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);

let _guard = BindGuard::new(&self.program);

for (p, v, ship) in (&position, &velocity, &ship).join() {
let _guard = match ship.type_ {
ShipType::Fighter => BindGuard::new(&self.texture_fighter),
ShipType::Bomber => BindGuard::new(&self.texture_bomber),
ShipType::Transporter => BindGuard::new(&self.texture_transporter),
};

let p_x = p.pos.x;
let p_y = p.pos.y;
let d_x = v.dir.x;
let d_y = v.dir.y;
let s = p.size;

let m = Matrix4f::new(
Vector4f::new(-s * d_y, s * d_x, 0.0, 0.0),
Vector4f::new(-s * d_x, -s * d_y, 0.0, 0.0),
Vector4f::new(0.0, 0.0, s, 0.0),
Vector4f::new(p_x, p_y, 0.0, 1.0),
);

if let Err(err) = self
.program
.uniform(self.model_location, Uniform::Matrix4f(&m))
{
error!("Error while updating model matrix: {}", err);
}

geometry.render_quad();
}

gl::disable(gl::BLEND);
}
}

+ 1
- 1
space-crush-app/src/resources/state.rs View File

@@ -3,7 +3,7 @@
use std::collections::HashSet;
use std::iter::IntoIterator;

use super::super::misc::{MouseButton, VirtualKeyCode};
use crate::misc::{MouseButton, VirtualKeyCode};

#[derive(Default)]
pub struct State {


+ 2
- 0
space-crush-common/src/components/mod.rs View File

@@ -1,7 +1,9 @@
mod planet;
mod position;
mod ship;
mod velocity;

pub use planet::Planet;
pub use position::Position;
pub use ship::{Ship, Type as ShipType};
pub use velocity::Velocity;

+ 18
- 0
space-crush-common/src/components/ship.rs View File

@@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};
use specs::{Component, VecStorage};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Ship {
pub type_: Type,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Type {
Fighter,
Bomber,
Transporter,
}

impl Component for Ship {
type Storage = VecStorage<Self>;
}

+ 6
- 17
space-crush-common/src/components/velocity.rs View File

@@ -1,24 +1,13 @@
use std::ops::{Deref, DerefMut};

use glc::vector::Vector2f;
use serde::{Deserialize, Serialize};
use specs::{Component, VecStorage};

pub struct Velocity(pub Vector2f);
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Velocity {
pub dir: Vector2f,
pub speed: f32,
}

impl Component for Velocity {
type Storage = VecStorage<Self>;
}

impl Deref for Velocity {
type Target = Vector2f;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for Velocity {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

+ 5
- 1
space-crush-common/src/dispatcher.rs View File

@@ -1,6 +1,9 @@
use specs::{Dispatcher as Inner, DispatcherBuilder, World};

use crate::{resources::Global, systems::Process};
use crate::{
resources::Global,
systems::{Movement, Process},
};

pub struct Dispatcher<'a, 'b> {
dispatcher: Inner<'a, 'b>,
@@ -12,6 +15,7 @@ impl<'a, 'b> Dispatcher<'a, 'b> {

let mut dispatcher = DispatcherBuilder::new()
.with(Process::default(), "process", &[])
.with(Movement::default(), "movement", &[])
.build();
dispatcher.setup(world);



+ 2
- 2
space-crush-common/src/misc/persistence.rs View File

@@ -1,6 +1,6 @@
use specs::saveload::SimpleMarker;

use crate::components::{Planet, Position};
use crate::components::{Planet, Position, Ship, Velocity};

use super::Persistence;

@@ -9,5 +9,5 @@ pub struct PersistWorldMarker;

impl Persistence for PersistWorld {
type Marker = SimpleMarker<PersistWorldMarker>;
type Components = (Position, Planet);
type Components = (Position, Velocity, Planet, Ship);
}

+ 2
- 0
space-crush-common/src/systems/mod.rs View File

@@ -1,3 +1,5 @@
mod movement;
mod process;

pub use movement::Movement;
pub use process::Process;

+ 36
- 0
space-crush-common/src/systems/movement.rs View File

@@ -0,0 +1,36 @@
#![allow(dead_code)]

use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage};

use crate::{
components::{Position, Velocity},
resources::Global,
};

#[derive(Default)]
pub struct Movement;

#[derive(SystemData)]
pub struct MovementData<'a> {
position: WriteStorage<'a, Position>,
velocity: ReadStorage<'a, Velocity>,
global: Read<'a, Global>,
}

impl<'a> System<'a> for Movement {
type SystemData = MovementData<'a>;

fn run(&mut self, data: Self::SystemData) {
let MovementData {
mut position,
velocity,
global,
} = data;

(&mut position, &velocity)
.par_join()
.for_each(|(position, velocity)| {
position.pos = position.pos + velocity.dir * velocity.speed * global.delta;
});
}
}

+ 1
- 1
space-crush-common/src/systems/process.rs View File

@@ -5,7 +5,7 @@ use std::time::Instant;

use specs::{System, Write};

use super::super::resources::Global;
use crate::resources::Global;

pub struct Process {
last_frame: Instant,


Loading…
Cancel
Save