186 lines
No EOL
6.9 KiB
C++
186 lines
No EOL
6.9 KiB
C++
#include "GameRenderer.h"
|
|
#include "client.hpp"
|
|
|
|
#include <moggle/math/projection.hpp>
|
|
|
|
namespace games {
|
|
|
|
template <size_t N>
|
|
std::vector<std::string> from_strarray(const char* const (& strs)[N]) {
|
|
std::vector<std::string> v(N);
|
|
for(size_t i = 0; i < N; ++i){
|
|
v.push_back(strs[i]);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
using namespace moggle;
|
|
using namespace motor;
|
|
GameRenderer::GameRenderer(int w, int h)
|
|
: ball_texture(::bundle.get_texture_path() + "bol.png")
|
|
{
|
|
gl::enable(GL_LINE_SMOOTH);
|
|
glLineWidth(1.5f);
|
|
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){
|
|
shader.s.clear();
|
|
shader.a = attributes;
|
|
|
|
try {
|
|
auto v = shader::from_file(shader_type::vertex, ::bundle.get_shader_path() + file + ".vsh");
|
|
auto f = shader::from_file(shader_type::fragment, ::bundle.get_shader_path() + file + ".fsh");
|
|
|
|
shader.s.attach(v);
|
|
shader.s.attach(f);
|
|
} catch (std::exception & e){
|
|
CERR << e.what();
|
|
}
|
|
|
|
for(auto str : attributes){
|
|
shader.s.bind_attribute(shader.attribute_location(str), str);
|
|
}
|
|
|
|
shader.s.link();
|
|
};
|
|
|
|
load_shader(ball_shader, "ball", {"position", "color", "texture_coordinate"});
|
|
load_shader(line_shader, "line", {"position", "color"});
|
|
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){
|
|
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 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()){
|
|
moggle::gl::blend_function(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
note_shader.s.use();
|
|
note_shader.s.uniform<matrix<float, 4>>("modelViewProjectionMatrix").set(modelViewProjectionMatrix);
|
|
|
|
// glVertexAttribPointer(it->second, size, type, normalized, stride, ptr);
|
|
gl::enable_vertex_attribute_array(note_shader.attribute_location("position"));
|
|
gl::vertex_attribute_pointer(note_shader.attribute_location("position"), 2, GL_FLOAT, GL_FALSE, sizeof(note_type), &client.beat.notes[0].information);
|
|
|
|
gl::draw_arrays(GL_POINTS, 0, client.beat.notes.size());
|
|
}
|
|
|
|
if(!client.lines.empty() || client.kick || client.snare){
|
|
moggle::gl::blend_function(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
line_shader.s.use();
|
|
line_shader.s.uniform<matrix<float, 4>>("modelViewProjectionMatrix").set(modelViewProjectionMatrix);
|
|
|
|
lines.clear();
|
|
lines.reserve(client.lines.size() * 2 + 2 * 2);
|
|
for(auto const & l : client.lines){
|
|
Color color = (l->line_kind == simulation::kFallThrough)
|
|
? Color{1.0f, l->color_intensity, std::sin(l->color_intensity)}
|
|
: Color{std::sin(l->color_intensity), 0.5f + 0.5f*l->color_intensity, 1.0f};
|
|
lines.push_back({l->starting_point, color});
|
|
lines.push_back({l->end_point, color});
|
|
}
|
|
|
|
if(client.kick){
|
|
Color color{0.6f + client.kick->color_intensity, 0.5f, 0.4f};
|
|
lines.push_back({client.kick->starting_point, color});
|
|
lines.push_back({client.kick->end_point, color});
|
|
}
|
|
if(client.snare){
|
|
Color color{0.6f + client.snare->color_intensity, 0.7f, 0.8f};
|
|
lines.push_back({client.snare->starting_point, color});
|
|
lines.push_back({client.snare->end_point, color});
|
|
}
|
|
|
|
if(debug_draw){
|
|
for(auto const & l : client.sim.lines){
|
|
Color color = (l.line_kind == simulation::kFallThrough) ? Color{1.0, 0.0, 0.0} : Color{0.0, 0.5, 1.0};
|
|
lines.push_back({l.starting_point, color});
|
|
lines.push_back({l.end_point, color});
|
|
}
|
|
}
|
|
|
|
gl::enable_vertex_attribute_array(line_shader.attribute_location("position"));
|
|
gl::vertex_attribute_pointer(line_shader.attribute_location("position"), 2, GL_FLOAT, GL_FALSE, sizeof(LineVertex), &lines[0]);
|
|
gl::enable_vertex_attribute_array(line_shader.attribute_location("color"));
|
|
gl::vertex_attribute_pointer(line_shader.attribute_location("color"), 3, GL_FLOAT, GL_FALSE, sizeof(LineVertex), &lines[0].color);
|
|
|
|
gl::draw_arrays(GL_LINES, 0, lines.size());
|
|
}
|
|
|
|
if(!client.sim.balls.empty()){
|
|
gl::blend_function(GL_ONE, GL_ONE);
|
|
ball_shader.s.use();
|
|
ball_shader.s.uniform<matrix<float, 4>>("modelViewProjectionMatrix").set(modelViewProjectionMatrix);
|
|
|
|
balls.clear();
|
|
balls.reserve(client.sim.balls.size());
|
|
for(auto const & b : client.sim.balls){
|
|
balls.emplace_back(b);
|
|
}
|
|
|
|
gl::enable_vertex_attribute_array(ball_shader.attribute_location("position"));
|
|
gl::vertex_attribute_pointer(ball_shader.attribute_location("position"), 3, GL_FLOAT, GL_FALSE, sizeof(BallQuad::Vertex), &balls[0].quad[0].x);
|
|
gl::enable_vertex_attribute_array(ball_shader.attribute_location("color"));
|
|
gl::vertex_attribute_pointer(ball_shader.attribute_location("color"), 3, GL_FLOAT, GL_FALSE, sizeof(BallQuad::Vertex), &balls[0].quad[0].r);
|
|
gl::enable_vertex_attribute_array(ball_shader.attribute_location("texture_coordinate"));
|
|
gl::vertex_attribute_pointer(ball_shader.attribute_location("texture_coordinate"), 2, GL_FLOAT, GL_FALSE, sizeof(BallQuad::Vertex), &balls[0].quad[0].s);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, ball_texture.get_id());
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
ball_shader.s.uniform<GLint>("texture").set(0);
|
|
|
|
gl::draw_arrays(GL_TRIANGLE_STRIP, 0, balls.size() * 6);
|
|
}
|
|
fbo1->unbind();
|
|
|
|
draw_square(flat_shader, fbo1);
|
|
}
|
|
} |