1
Fork 0
This repository has been archived on 2025-04-09. You can view files and clone it, but cannot push or open issues or pull requests.
beats-motor-client/src/client/GameRenderer.cpp
2013-04-23 17:06:46 +02:00

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);
}
}