Parcourir la source

Implemented render system for planets

raster
Bergmann89 il y a 5 ans
Parent
révision
09b6b583bf
19 fichiers modifiés avec 256 ajouts et 106 suppressions
  1. +3
    -0
      glc/src/shader.rs
  2. +35
    -0
      space-crush-app/resources/shader/planet.frag
  3. +22
    -0
      space-crush-app/resources/shader/planet.vert
  4. +2
    -2
      space-crush-app/resources/shader/quad.frag
  5. +2
    -2
      space-crush-app/resources/shader/quad.vert
  6. +2
    -2
      space-crush-app/resources/shader/text.frag
  7. +7
    -7
      space-crush-app/resources/shader/text.vert
  8. +4
    -3
      space-crush-app/src/lib.rs
  9. +17
    -0
      space-crush-app/src/main.rs
  10. +5
    -1
      space-crush-app/src/misc/world.rs
  11. +7
    -1
      space-crush-app/src/render/init.rs
  12. +2
    -2
      space-crush-app/src/render/mod.rs
  13. +88
    -0
      space-crush-app/src/render/planets.rs
  14. +0
    -69
      space-crush-app/src/render/test.rs
  15. +2
    -0
      space-crush-app/src/resources/mod.rs
  16. +42
    -0
      space-crush-app/src/resources/uniform.rs
  17. +4
    -0
      space-crush-common/src/components/mod.rs
  18. +8
    -0
      space-crush-common/src/components/planet.rs
  19. +4
    -17
      space-crush-common/src/components/position.rs

+ 3
- 0
glc/src/shader.rs Voir le fichier

@@ -8,6 +8,7 @@ use crate::{
error::Error,
matrix::Matrix4f,
misc::{AsEnum, Bindable},
vector::Vector4f,
};

/* Programm */
@@ -76,6 +77,7 @@ impl Program {
pub fn uniform(&self, location: gl::GLint, uniform: Uniform<'_>) {
match uniform {
Uniform::Matrix4f(v) => gl::uniform_matrix_4fv(location, 1, gl::FALSE, v.as_ptr()),
Uniform::Vector4f(v) => gl::uniform_4fv(location, 1, v.as_ptr()),
}
}
}
@@ -208,4 +210,5 @@ impl AsEnum for Type {

pub enum Uniform<'a> {
Matrix4f(&'a Matrix4f),
Vector4f(&'a Vector4f),
}

+ 35
- 0
space-crush-app/resources/shader/planet.frag Voir le fichier

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

const float GLOW_STEP_0 = 0.480; // inner (min = 0.0)
const float GLOW_STEP_1 = 0.975; // outer (max = 0.5)
const float GLOW_PULSE_SIZE_0 = 0.010; // inner (+/-)
const float GLOW_PULSE_SIZE_1 = 0.025; // outer (+/-)
const float GLOW_PULSE_TIME = 2.000;

in FragmentData {
vec2 texCoords;
} data;

layout (std140, binding = 2) uniform Global {
float time;
} global;

layout(location = 3) uniform vec4 glowColor;

uniform sampler2D tex;

out vec4 color;

void main() {
vec2 texCoords = data.texCoords - vec2(0.5);
float radius = length(texCoords);
float bgPulse = sin(GLOW_PULSE_TIME * global.time);
float alpha = 1.0 - smoothstep(
GLOW_STEP_0 + GLOW_PULSE_SIZE_0 * bgPulse,
GLOW_STEP_1 + GLOW_PULSE_SIZE_1 * bgPulse,
radius);

vec4 tex = texture(tex, data.texCoords);
vec4 glow = vec4(glowColor.rgb, glowColor.a * alpha);
color = tex * tex.a + glow * (1.0 - tex.a);
}

+ 22
- 0
space-crush-app/resources/shader/planet.vert Voir le fichier

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

const float GLOW_SIZE_FACTOR = 2.00;

layout (location = 0) in vec3 position;

layout (std140, binding = 0) uniform Camera {
mat4 projection;
mat4 view;
vec2 size;
} camera;

layout (location = 1) uniform mat4 model;

out FragmentData {
vec2 texCoords;
} data;

void main() {
data.texCoords = position.xy * GLOW_SIZE_FACTOR + vec2(0.5);
gl_Position = camera.projection * camera.view * model * vec4(position * GLOW_SIZE_FACTOR, 1.0);
}

+ 2
- 2
space-crush-app/resources/shader/quad.frag Voir le fichier

@@ -1,7 +1,7 @@
#version 450 core

in FragmentData {
vec2 tex_coords;
vec2 texCoords;
} data;

uniform sampler2D tex;
@@ -9,5 +9,5 @@ uniform sampler2D tex;
out vec4 color;

void main() {
color = texture(tex, data.tex_coords);
color = texture(tex, data.texCoords);
}

+ 2
- 2
space-crush-app/resources/shader/quad.vert Voir le fichier

@@ -11,10 +11,10 @@ layout (std140, binding = 0) uniform Camera {
layout (location = 1) uniform mat4 model;

out FragmentData {
vec2 tex_coords;
vec2 texCoords;
} data;

void main() {
data.tex_coords = position.xy + vec2(0.5);
data.texCoords = position.xy + vec2(0.5);
gl_Position = camera.projection * camera.view * model * vec4(position, 1.0);
}

+ 2
- 2
space-crush-app/resources/shader/text.frag Voir le fichier

@@ -1,7 +1,7 @@
#version 450 core

in FragmentData {
vec2 tex_coord;
vec2 texCoords;
vec4 color;
} data;

@@ -10,7 +10,7 @@ uniform sampler2D tex;
out vec4 color;

void main() {
float alpha = texture(tex, data.tex_coord).r;
float alpha = texture(tex, data.texCoords).r;

if (alpha <= 0.0) {
discard;


+ 7
- 7
space-crush-app/resources/shader/text.vert Voir le fichier

@@ -15,33 +15,33 @@ layout (std140, binding = 0) uniform Camera {
layout (location = 1) uniform mat4 model;

out FragmentData {
vec2 tex_coord;
vec2 texCoords;
vec4 color;
} data;

void main() {
vec2 position = vec2(0.0);
vec2 tex_coord = vec2(0.0);
vec2 texCoords = vec2(0.0);

switch (gl_VertexID) {
case 0:
position = vec2(pos_min.x, pos_max.y);
tex_coord = vec2(tex_min.x, tex_max.y);
texCoords = vec2(tex_min.x, tex_max.y);
break;

case 1:
position = vec2(pos_min.x, pos_min.y);
tex_coord = vec2(tex_min.x, tex_min.y);
texCoords = vec2(tex_min.x, tex_min.y);
break;

case 2:
position = vec2(pos_max.x, pos_max.y);
tex_coord = vec2(tex_max.x, tex_max.y);
texCoords = vec2(tex_max.x, tex_max.y);
break;

case 3:
position = vec2(pos_max.x, pos_min.y);
tex_coord = vec2(tex_max.x, tex_min.y);
texCoords = vec2(tex_max.x, tex_min.y);
break;
}

@@ -54,6 +54,6 @@ void main() {

gl_Position = ortho * vec4(position, 0.0, 1.0);

data.tex_coord = tex_coord;
data.texCoords = texCoords;
data.color = color;
}

+ 4
- 3
space-crush-app/src/lib.rs Voir le fichier

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

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

pub struct App<'a, 'b> {
@@ -28,6 +28,7 @@ impl<'a, 'b> App<'a, 'b> {

world.insert(config);
world.insert(Camera::new()?);
world.insert(Uniform::new()?);
world.insert(Geometry::new()?);
world.insert(State::default());

@@ -36,7 +37,7 @@ impl<'a, 'b> App<'a, 'b> {
let mut dispatcher = DispatcherBuilder::new()
.with(StateUpdate::new(world)?, "state_update", &[])
.with_thread_local(Init::new(world)?)
.with_thread_local(Test::new(world)?)
.with_thread_local(Planets::new(world)?)
.with_thread_local(Debug::new(&text_manager)?)
.build();
dispatcher.setup(world);


+ 17
- 0
space-crush-app/src/main.rs Voir le fichier

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

create_test_world(&mut world);

while app.is_running() {
common.process(&world);
app.process(&world)?;
@@ -40,3 +42,18 @@ fn run(vfs: Vfs) -> Result<(), Error> {

Ok(())
}

fn create_test_world(world: &mut World) {
use glc::vector::Vector2f;
use space_crush_common::components::{Planet, Position};
use specs::Builder;

world
.create_entity()
.with(Position {
pos: Vector2f::default(),
size: 500.0,
})
.with(Planet)
.build();
}

+ 5
- 1
space-crush-app/src/misc/world.rs Voir le fichier

@@ -42,7 +42,11 @@ impl WorldHelper for World {
let mut texture = Texture::new(Target::Texture2D)?;
texture.upload(&data, true)?;
texture.set_filter(FilterMin::LinearMipmapLinear, FilterMag::Linear)?;
texture.set_wrap(Wrap::ClampToEdge, Wrap::ClampToEdge, Wrap::ClampToEdge)?;
texture.set_wrap(
Wrap::ClampToBorder,
Wrap::ClampToBorder,
Wrap::ClampToBorder,
)?;

Ok(texture)
}


+ 7
- 1
space-crush-app/src/render/init.rs Voir le fichier

@@ -11,7 +11,7 @@ use specs::{prelude::*, ReadExpect, System, World, WriteExpect};

use crate::{
misc::{MouseEvent, WorldHelper},
resources::{Camera, Config, Geometry, State},
resources::{Camera, Config, Geometry, State, Uniform},
Error,
};

@@ -41,6 +41,7 @@ impl Init {
#[derive(SystemData)]
pub struct InitData<'a> {
camera: WriteExpect<'a, Camera>,
uniform: WriteExpect<'a, Uniform>,
state: ReadExpect<'a, State>,
config: ReadExpect<'a, Config>,
geometry: ReadExpect<'a, Geometry>,
@@ -53,6 +54,7 @@ impl<'a> System<'a> for Init {
fn run(&mut self, data: Self::SystemData) {
let InitData {
mut camera,
mut uniform,
state,
config,
geometry,
@@ -106,6 +108,10 @@ impl<'a> System<'a> for Init {
}
}

if let Err(err) = uniform.update() {
error!("Error while updating global uniform data: {}", err);
}

/* render background */
self.program.bind();
geometry.render_quad();


+ 2
- 2
space-crush-app/src/render/mod.rs Voir le fichier

@@ -1,7 +1,7 @@
mod debug;
mod init;
mod test;
mod planets;

pub use debug::Debug;
pub use init::Init;
pub use test::Test;
pub use planets::Planets;

+ 88
- 0
space-crush-app/src/render/planets.rs Voir le fichier

@@ -0,0 +1,88 @@
use glc::{
matrix::Matrix4f,
misc::Bindable,
shader::{Program, Type, Uniform},
texture::Texture,
vector::Vector4f,
};
use space_crush_common::{
components::{Planet, Position},
misc::WorldHelper as _,
};
use specs::{prelude::*, ReadExpect, ReadStorage, System, World};

use crate::{
misc::WorldHelper,
resources::{Camera, Geometry, Uniform as GlobalUniform},
Error,
};

pub struct Planets {
program: Program,
texture: Texture,
}

impl Planets {
pub fn new(world: &World) -> Result<Self, Error> {
let program = world.load_program(vec![
(Type::Vertex, "resources/shader/planet.vert"),
(Type::Fragment, "resources/shader/planet.frag"),
])?;
program.bind();
world.resource::<Camera>()?.bind(0)?;
world.resource::<GlobalUniform>()?.bind(2)?;
program.uniform(3, Uniform::Vector4f(&Vector4f::new(1.0, 1.0, 1.0, 0.1)));
program.unbind();

let texture = world.load_texture("resources/textures/planet01.png")?;

Ok(Self { program, texture })
}
}

#[derive(SystemData)]
pub struct PlanetsData<'a> {
geometry: ReadExpect<'a, Geometry>,
position: ReadStorage<'a, Position>,
planet: ReadStorage<'a, Planet>,
}

impl<'a> System<'a> for Planets {
type SystemData = PlanetsData<'a>;

fn run(&mut self, data: Self::SystemData) {
let PlanetsData {
geometry,
position,
planet,
} = data;

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

self.texture.bind();
self.program.bind();

for (p, _) in (&position, &planet).join() {
let x = p.pos.x;
let y = p.pos.y;
let s = p.size;

let m = Matrix4f::new(
Vector4f::new(s, 0.0, 0.0, 0.0),
Vector4f::new(0.0, s, 0.0, 0.0),
Vector4f::new(0.0, 0.0, s, 0.0),
Vector4f::new(x, y, 0.0, 1.0),
);

self.program.uniform(1, Uniform::Matrix4f(&m));

geometry.render_quad();
}

self.program.unbind();
self.texture.unbind();

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

+ 0
- 69
space-crush-app/src/render/test.rs Voir le fichier

@@ -1,69 +0,0 @@
use glc::{
matrix::{Angle, Matrix4f},
misc::Bindable,
shader::{Program, Type, Uniform},
texture::Texture,
vector::Vector3f,
};
use space_crush_common::{misc::WorldHelper as _, resources::Global};
use specs::{ReadExpect, System, World};

use crate::{
misc::WorldHelper,
resources::{Camera, Geometry},
Error,
};

pub struct Test {
model: Matrix4f,
program: Program,
texture: Texture,
}

impl Test {
pub fn new(world: &World) -> Result<Self, Error> {
let model = Matrix4f::scale(Vector3f::new(500.0, 500.0, 500.0));

let program = world.load_program(vec![
(Type::Vertex, "resources/shader/quad.vert"),
(Type::Fragment, "resources/shader/quad.frag"),
])?;
program.bind();
world.resource::<Camera>()?.bind(0)?;
program.unbind();

let texture = world.load_texture("resources/textures/planet01.png")?;

Ok(Self {
model,
program,
texture,
})
}
}

impl<'a> System<'a> for Test {
type SystemData = (ReadExpect<'a, Global>, ReadExpect<'a, Geometry>);

fn run(&mut self, (global, geometry): Self::SystemData) {
self.model = self.model
* Matrix4f::rotate(
Vector3f::new(0.0, 0.0, 1.0),
Angle::Deg(10.0 * global.delta),
);

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

self.texture.bind();
self.program.bind();
self.program.uniform(1, Uniform::Matrix4f(&self.model));

geometry.render_quad();

self.program.unbind();
self.texture.unbind();

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

+ 2
- 0
space-crush-app/src/resources/mod.rs Voir le fichier

@@ -2,8 +2,10 @@ mod camera;
mod config;
mod geometry;
mod state;
mod uniform;

pub use camera::Camera;
pub use config::Config;
pub use geometry::Geometry;
pub use state::State;
pub use uniform::Uniform;

+ 42
- 0
space-crush-app/src/resources/uniform.rs Voir le fichier

@@ -0,0 +1,42 @@
use std::time::Instant;

use glc::{
array_buffer::{ArrayBuffer, Target, Usage},
error::Error,
};

pub struct Uniform {
buffer: ArrayBuffer,
start_time: Instant,
}

#[repr(C, packed)]
struct Data {
time: f32,
}

impl Uniform {
pub fn new() -> Result<Self, Error> {
let mut buffer = ArrayBuffer::new(Target::UniformBuffer)?;
buffer.buffer_data(Usage::StaticDraw, &[Data { time: 0.0 }])?;

Ok(Self {
buffer,
start_time: Instant::now(),
})
}

pub fn update(&mut self) -> Result<(), Error> {
let time = Instant::now().duration_since(self.start_time).as_secs_f32();

let mut data = self.buffer.map_mut::<Data>(true)?;

data[0].time = time;

Ok(())
}

pub fn bind(&self, index: gl::GLuint) -> Result<(), Error> {
Error::checked(|| self.buffer.bind_buffer_base(index))
}
}

+ 4
- 0
space-crush-common/src/components/mod.rs Voir le fichier

@@ -1,3 +1,7 @@
mod planet;
mod position;
mod velocity;

pub use planet::Planet;
pub use position::Position;
pub use velocity::Velocity;

+ 8
- 0
space-crush-common/src/components/planet.rs Voir le fichier

@@ -0,0 +1,8 @@
use specs::{Component, NullStorage};

#[derive(Default)]
pub struct Planet;

impl Component for Planet {
type Storage = NullStorage<Self>;
}

+ 4
- 17
space-crush-common/src/components/position.rs Voir le fichier

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

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

pub struct Position(pub Vector2f);
pub struct Position {
pub pos: Vector2f,
pub size: f32,
}

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

impl Deref for Position {
type Target = Vector2f;

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

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

Chargement…
Annuler
Enregistrer