Made a more awesome renderer
This commit is contained in:
parent
76e3b7854e
commit
f9015fe05d
4 changed files with 147 additions and 46 deletions
|
@ -4,22 +4,6 @@
|
||||||
#include <moggle/math/projection.hpp>
|
#include <moggle/math/projection.hpp>
|
||||||
|
|
||||||
namespace games {
|
namespace games {
|
||||||
constexpr static const char* ball_attributes[] = {
|
|
||||||
"position",
|
|
||||||
"color",
|
|
||||||
"speed",
|
|
||||||
"texture_coordinate"
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr static const char* line_attributes[] = {
|
|
||||||
"position",
|
|
||||||
"color"
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr static const char* note_attributes[] = {
|
|
||||||
"position",
|
|
||||||
"color"
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
std::vector<std::string> from_strarray(const char* const (& strs)[N]) {
|
std::vector<std::string> from_strarray(const char* const (& strs)[N]) {
|
||||||
|
@ -32,14 +16,22 @@ std::vector<std::string> from_strarray(const char* const (& strs)[N]) {
|
||||||
|
|
||||||
using namespace moggle;
|
using namespace moggle;
|
||||||
using namespace motor;
|
using namespace motor;
|
||||||
GameRenderer::GameRenderer()
|
GameRenderer::GameRenderer(int w, int h)
|
||||||
: ball_texture(::bundle.get_texture_path() + "bol.png")
|
: ball_texture(::bundle.get_texture_path() + "bol.png")
|
||||||
{
|
{
|
||||||
gl::enable(GL_LINE_SMOOTH);
|
gl::enable(GL_LINE_SMOOTH);
|
||||||
glLineWidth(1.5f);
|
glLineWidth(1.5f);
|
||||||
glPointSize(4.0f);
|
glPointSize(4.0f);
|
||||||
|
|
||||||
|
load_shaders();
|
||||||
|
|
||||||
|
fbo1 = std::make_shared<motor::Fbo>(w, h);
|
||||||
|
fbo2 = std::make_shared<motor::Fbo>(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameRenderer::load_shaders(){
|
||||||
auto load_shader = [](Shader & shader, std::string file, std::vector<std::string> attributes){
|
auto load_shader = [](Shader & shader, std::string file, std::vector<std::string> attributes){
|
||||||
|
shader.s.clear();
|
||||||
shader.a = attributes;
|
shader.a = attributes;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -52,7 +44,7 @@ GameRenderer::GameRenderer()
|
||||||
CERR << e.what();
|
CERR << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto str : ball_attributes){
|
for(auto str : attributes){
|
||||||
shader.s.bind_attribute(shader.attribute_location(str), str);
|
shader.s.bind_attribute(shader.attribute_location(str), str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,14 +54,51 @@ GameRenderer::GameRenderer()
|
||||||
load_shader(ball_shader, "ball", {"position", "color", "texture_coordinate"});
|
load_shader(ball_shader, "ball", {"position", "color", "texture_coordinate"});
|
||||||
load_shader(line_shader, "line", {"position", "color"});
|
load_shader(line_shader, "line", {"position", "color"});
|
||||||
load_shader(note_shader, "note", {"position"});
|
load_shader(note_shader, "note", {"position"});
|
||||||
|
load_shader(flat_shader, "flat", {"position", "texture_coordinate"});
|
||||||
|
load_shader(awe_shader, "awe", {"position", "texture_coordinate"});
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_square(GameRenderer::Shader & shader, std::shared_ptr<motor::Fbo> read_fbo){
|
||||||
|
shader.s.use();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, read_fbo->get_texture_id());
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
shader.s.uniform<GLint>("texture").set(0);
|
||||||
|
|
||||||
|
typedef GLfloat Quad[4];
|
||||||
|
static Quad quad [] = {
|
||||||
|
{-1, 1, 0, 1},
|
||||||
|
{ 1, 1, 1, 1},
|
||||||
|
{-1, -1, 0, 0},
|
||||||
|
{ 1, -1, 1, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
gl::enable_vertex_attribute_array(shader.attribute_location("position"));
|
||||||
|
gl::vertex_attribute_pointer(shader.attribute_location("position"), 2, GL_FLOAT, GL_FALSE, sizeof(Quad), &quad[0][0]);
|
||||||
|
gl::enable_vertex_attribute_array(shader.attribute_location("texture_coordinate"));
|
||||||
|
gl::vertex_attribute_pointer(shader.attribute_location("texture_coordinate"), 2, GL_FLOAT, GL_FALSE, sizeof(Quad), &quad[0][2]);
|
||||||
|
|
||||||
|
gl::draw_arrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::draw(Client const & client){
|
void GameRenderer::draw(Client const & client){
|
||||||
gl::disable(GL_DEPTH_TEST);
|
gl::disable(GL_DEPTH_TEST);
|
||||||
|
gl::disable(GL_CULL_FACE);
|
||||||
|
|
||||||
auto projectionMatrix = projection_matrices::orthographic(client.sim.bounds.xmin, client.sim.bounds.xmax, client.sim.bounds.ymax, client.sim.bounds.ymin, -100.0f, 100.0f);
|
auto projectionMatrix = projection_matrices::orthographic(client.sim.bounds.xmin, client.sim.bounds.xmax, client.sim.bounds.ymax, client.sim.bounds.ymin, -100.0f, 100.0f);
|
||||||
auto modelViewProjectionMatrix = projectionMatrix;
|
auto modelViewProjectionMatrix = projectionMatrix;
|
||||||
|
|
||||||
|
std::swap(fbo1, fbo2);
|
||||||
|
fbo1->bind();
|
||||||
|
{
|
||||||
|
awe_shader.s.use();
|
||||||
|
awe_shader.s.uniform<GLfloat>("time").set(client.time);
|
||||||
|
awe_shader.s.uniform<GLfloat>("beat").set(client.beat.time);
|
||||||
|
awe_shader.s.uniform<moggle::vector2<GLfloat>>("inv_wh").set({1.0 / fbo1->get_width(), 1.0 / fbo1->get_height()});
|
||||||
|
draw_square(awe_shader, fbo2);
|
||||||
|
}
|
||||||
|
|
||||||
if(!client.beat.notes.empty()){
|
if(!client.beat.notes.empty()){
|
||||||
moggle::gl::blend_function(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
moggle::gl::blend_function(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
note_shader.s.use();
|
note_shader.s.use();
|
||||||
|
@ -133,12 +162,14 @@ void GameRenderer::draw(Client const & client){
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, ball_texture.get_id());
|
glBindTexture(GL_TEXTURE_2D, ball_texture.get_id());
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
ball_shader.s.uniform<GLint>("texture").set(0);
|
ball_shader.s.uniform<GLint>("texture").set(0);
|
||||||
|
|
||||||
gl::draw_arrays(GL_TRIANGLE_STRIP, 0, balls.size() * 6);
|
gl::draw_arrays(GL_TRIANGLE_STRIP, 0, balls.size() * 6);
|
||||||
}
|
}
|
||||||
|
fbo1->unbind();
|
||||||
|
|
||||||
|
draw_square(flat_shader, fbo1);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,14 +18,14 @@ struct BallQuad {
|
||||||
// degenerate
|
// degenerate
|
||||||
std::array<Vertex, 6> quad;
|
std::array<Vertex, 6> quad;
|
||||||
BallQuad(ball_type const & b){
|
BallQuad(ball_type const & b){
|
||||||
quad = {
|
quad = {{
|
||||||
Vertex{b.position.x-hsize, b.position.y-hsize, 0.0f, 0.9f, 0.4f, 0.1f, 0.0f, 0.0f},
|
Vertex{b.position.x-hsize, b.position.y-hsize, 0.0f, 0.9f, 0.4f, 0.1f, 0.0f, 0.0f},
|
||||||
Vertex{b.position.x-hsize, b.position.y-hsize, 0.0f, 0.9f, 0.4f, 0.1f, 0.0f, 0.0f},
|
Vertex{b.position.x-hsize, b.position.y-hsize, 0.0f, 0.9f, 0.4f, 0.1f, 0.0f, 0.0f},
|
||||||
Vertex{b.position.x+hsize, b.position.y-hsize, 0.0f, 0.9f, 0.4f, 0.1f, 1.0f, 0.0f},
|
Vertex{b.position.x+hsize, b.position.y-hsize, 0.0f, 0.9f, 0.4f, 0.1f, 1.0f, 0.0f},
|
||||||
Vertex{b.position.x-hsize, b.position.y+hsize, 0.0f, 0.9f, 0.4f, 0.1f, 0.0f, 1.0f},
|
Vertex{b.position.x-hsize, b.position.y+hsize, 0.0f, 0.9f, 0.4f, 0.1f, 0.0f, 1.0f},
|
||||||
Vertex{b.position.x+hsize, b.position.y+hsize, 0.0f, 0.9f, 0.4f, 0.1f, 1.0f, 1.0f},
|
Vertex{b.position.x+hsize, b.position.y+hsize, 0.0f, 0.9f, 0.4f, 0.1f, 1.0f, 1.0f},
|
||||||
Vertex{b.position.x+hsize, b.position.y+hsize, 0.0f, 0.9f, 0.4f, 0.1f, 1.0f, 1.0f},
|
Vertex{b.position.x+hsize, b.position.y+hsize, 0.0f, 0.9f, 0.4f, 0.1f, 1.0f, 1.0f},
|
||||||
};
|
}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,12 +59,19 @@ struct GameRenderer {
|
||||||
Shader ball_shader;
|
Shader ball_shader;
|
||||||
Shader line_shader;
|
Shader line_shader;
|
||||||
Shader note_shader;
|
Shader note_shader;
|
||||||
|
Shader flat_shader;
|
||||||
|
Shader awe_shader;
|
||||||
motor::Texture ball_texture;
|
motor::Texture ball_texture;
|
||||||
|
|
||||||
|
std::shared_ptr<motor::Fbo> fbo1;
|
||||||
|
std::shared_ptr<motor::Fbo> fbo2;
|
||||||
|
|
||||||
bool debug_draw{false};
|
bool debug_draw{false};
|
||||||
|
|
||||||
GameRenderer();
|
GameRenderer(int w, int h);
|
||||||
|
|
||||||
void draw(Client const & client);
|
void draw(Client const & client);
|
||||||
|
|
||||||
|
void load_shaders();
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <lib/libwebsockets.h>
|
#include <lib/libwebsockets.h>
|
||||||
|
@ -81,6 +82,7 @@ namespace games {
|
||||||
|
|
||||||
Client::Client(int window_width_, int window_height_, std::shared_ptr<Base>& active_base_)
|
Client::Client(int window_width_, int window_height_, std::shared_ptr<Base>& active_base_)
|
||||||
: Base(window_width_, window_height_, active_base_)
|
: Base(window_width_, window_height_, active_base_)
|
||||||
|
, game_renderer(window_width_, window_height_)
|
||||||
{
|
{
|
||||||
if(current_client){
|
if(current_client){
|
||||||
CERR << "Warning: global client already defined\n";
|
CERR << "Warning: global client already defined\n";
|
||||||
|
@ -88,14 +90,20 @@ namespace games {
|
||||||
current_client = this;
|
current_client = this;
|
||||||
|
|
||||||
// sound
|
// sound
|
||||||
scale = Scale::load_from_file(*current_scale);
|
for(auto & str : scale_files){
|
||||||
|
scales.push_back(Scale::load_from_file(str));
|
||||||
|
}
|
||||||
|
scale = scales[0];
|
||||||
|
|
||||||
|
chords.notes.emplace_back(note_type::kWholeNote, note_info{100.0f, 100.0f});
|
||||||
|
|
||||||
// simulation
|
// simulation
|
||||||
sim.bounds.xmax = window_width_;
|
sim.bounds.xmax = window_width_;
|
||||||
sim.bounds.ymax = window_height_;
|
sim.bounds.ymax = window_height_;
|
||||||
beat.notes.emplace_back(note_type::kQuarterNote, note_info{100.0f, 100.0f});
|
|
||||||
cheap_line_type line{{{50.0f, 100.0f}, {150.0f, 200.0f}, simulation::kOneWay}};
|
beat.notes.emplace_back(note_type::kQuarterNote, note_info{window_width / 5.0f, 10.0f});
|
||||||
add_line(line);
|
beat.notes.emplace_back(note_type::kWholeNote, note_info{window_width / 2.0f, 10.0f});
|
||||||
|
beat.notes.emplace_back(note_type::kHalfNote, note_info{4.0f * window_width / 5.0f, 10.0f});
|
||||||
|
|
||||||
// websockets
|
// websockets
|
||||||
lws_context_creation_info info;
|
lws_context_creation_info info;
|
||||||
|
@ -127,22 +135,32 @@ namespace games {
|
||||||
void Client::handle_input(float dt, Input input){
|
void Client::handle_input(float dt, Input input){
|
||||||
using motor::Position;
|
using motor::Position;
|
||||||
|
|
||||||
if(input.keys_went_down[SDLK_u]){
|
if(input.keys_went_down[SDLK_b]){
|
||||||
//Iterates over drawing the physics and normal world, drawing only the physics world, and drawing only the normal world.
|
sim.balls.clear();
|
||||||
if(!draw_physics_world){
|
}
|
||||||
draw_physics_world = true;
|
|
||||||
} else {
|
if(input.keys_went_down[SDLK_l]){
|
||||||
if(draw_only_physics_world){
|
lines.clear();
|
||||||
draw_physics_world = false;
|
sim.lines.clear();
|
||||||
draw_only_physics_world = false;
|
}
|
||||||
} else {
|
|
||||||
draw_only_physics_world = true;
|
if(input.keys_went_down[SDLK_r]){
|
||||||
}
|
scales.clear();
|
||||||
|
for(auto & str : scale_files){
|
||||||
|
scales.push_back(Scale::load_from_file(str));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(input.keys_went_down[SDLK_k]){
|
if(input.keys_went_down[SDLK_k]){
|
||||||
scene->update_shader_pipeline();
|
scene->update_shader_pipeline();
|
||||||
|
game_renderer.load_shaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(char n = '0'; n <= '9'; ++n){
|
||||||
|
if(input.keys_went_down[n]){
|
||||||
|
scale = scales[n - '0'];
|
||||||
|
update_pitches(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,19 +176,36 @@ namespace games {
|
||||||
|
|
||||||
scene->camera.set_position({0, 0, 20});
|
scene->camera.set_position({0, 0, 20});
|
||||||
|
|
||||||
|
float dt2 = dt;
|
||||||
|
if(dt2 > 1.0/70.0 && dt2 < 1.0/55.0) dt2 = 1.0/60.0;
|
||||||
|
|
||||||
// simulation
|
// simulation
|
||||||
for(auto l : lines){
|
for(auto l : lines){
|
||||||
l->update(dt);
|
l->update(dt2);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto x : sim.update(dt)){
|
for(auto x : sim.update(dt2)){
|
||||||
x.line.information->play();
|
x.line.information->play();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto n : beat.update(dt)){
|
for(auto n : beat.update(music_speed * dt2)){
|
||||||
sim.balls.emplace_back(n.x, n.y, 0, 0, balluid++);
|
sim.balls.emplace_back(n.x, n.y, 0, 0, balluid++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!chords.update(music_speed * dt2).empty()){
|
||||||
|
std::cout << std::distance(chord_progression.cbegin(), chord_progression_it) + 1 << "th chord\n";
|
||||||
|
scale = scales[*chord_progression_it];
|
||||||
|
update_pitches(*this);
|
||||||
|
|
||||||
|
++chord_progression_it;
|
||||||
|
if(chord_progression_it == chord_progression.end()){
|
||||||
|
int i = rand() % chord_progressions.size();
|
||||||
|
std::cout << "Changing progression: " << i << std::endl;
|
||||||
|
chord_progression = chord_progressions[i];
|
||||||
|
chord_progression_it = chord_progression.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// websockets
|
// websockets
|
||||||
const float push_interval = 0.05;
|
const float push_interval = 0.05;
|
||||||
push_time += dt;
|
push_time += dt;
|
||||||
|
|
|
@ -15,6 +15,14 @@
|
||||||
#include "client_common.hpp"
|
#include "client_common.hpp"
|
||||||
#include "GameRenderer.h"
|
#include "GameRenderer.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Controls:
|
||||||
|
1, .. 9, 0: change chord (will also be done automatically)
|
||||||
|
r: reload scales (aka chords)
|
||||||
|
k: reload shaders
|
||||||
|
b: clear balls
|
||||||
|
l: clear lines
|
||||||
|
*/
|
||||||
|
|
||||||
namespace games {
|
namespace games {
|
||||||
struct Client : public Base {
|
struct Client : public Base {
|
||||||
|
@ -32,20 +40,40 @@ namespace games {
|
||||||
|
|
||||||
simu_type sim;
|
simu_type sim;
|
||||||
beat_type beat;
|
beat_type beat;
|
||||||
|
beat_type chords;
|
||||||
|
|
||||||
void add_line(cheap_line_type const & line);
|
void add_line(cheap_line_type const & line);
|
||||||
|
|
||||||
// Sound part
|
// Sound part
|
||||||
const std::vector<std::string> scales{
|
const std::vector<std::string> scale_files{
|
||||||
::bundle.get_sound_path() + "maj7.txt",
|
::bundle.get_sound_path() + "pentatonic.txt", // 0 a
|
||||||
::bundle.get_sound_path() + "pentatonic"
|
::bundle.get_sound_path() + "c.txt", // 1 c
|
||||||
|
::bundle.get_sound_path() + "d.txt", // 2 d
|
||||||
|
::bundle.get_sound_path() + "em.txt", // 3 e
|
||||||
|
::bundle.get_sound_path() + "maj7.txt", // 4 g
|
||||||
|
::bundle.get_sound_path() + "noon.txt", // 5 a
|
||||||
|
::bundle.get_sound_path() + "cnoon.txt", // 6 c
|
||||||
|
::bundle.get_sound_path() + "blues.txt", // 7 a
|
||||||
|
::bundle.get_sound_path() + "spanish.txt", // 8 a
|
||||||
|
::bundle.get_sound_path() + "f.txt", // 9 f
|
||||||
};
|
};
|
||||||
|
std::vector<Scale> scales;
|
||||||
|
Scale scale;
|
||||||
|
|
||||||
|
const std::vector<std::vector<int>> chord_progressions{
|
||||||
|
{1, 2, 3, 3, 1, 2, 3, 4, 1, 2, 3, 3, 1, 2, 3, 4},
|
||||||
|
{0, 7, 4, 4, 0, 1, 9, 3},
|
||||||
|
{0, 0, 9, 9, 0, 0, 5, 6}
|
||||||
|
};
|
||||||
|
std::vector<int> chord_progression{chord_progressions[0]};
|
||||||
|
std::vector<int>::const_iterator chord_progression_it{chord_progression.begin()};
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<motor::al::Buffer>> sounds{
|
const std::vector<std::shared_ptr<motor::al::Buffer>> sounds{
|
||||||
resource_cache.get_sound_buffer(::bundle.get_sound_path() + "guitar440.wav"),
|
resource_cache.get_sound_buffer(::bundle.get_sound_path() + "guitar440.wav"),
|
||||||
resource_cache.get_sound_buffer(::bundle.get_sound_path() + "marimba.wav")
|
resource_cache.get_sound_buffer(::bundle.get_sound_path() + "marimba.wav")
|
||||||
};
|
};
|
||||||
std::vector<std::string>::const_iterator current_scale{scales.begin()};
|
|
||||||
Scale scale;
|
float music_speed{1.0};
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
GameRenderer game_renderer;
|
GameRenderer game_renderer;
|
||||||
|
|
Reference in a new issue