// // App.h // GLGameTemplate // // Created by Joshua Moerman on 5/4/12. // Copyright (c) 2012 Vadovas. All rights reserved. // #ifndef GLGameTemplate_App_h #define GLGameTemplate_App_h #import #include #include #include "shader.h" #include "fbo.h" #include "interpolator.h" #include "statics.h" #define kWindowWidth 1024 #define kWindowHeight 768 #define kFBOWidth 128 #define kFBOHeight 128 struct App { constexpr static int preferred_frames_per_second(){ return 60; } constexpr static bool multisample(){ return false; } constexpr static bool depth(){ return true; } constexpr static std::vector get_attributes(){ std::vector v; v.push_back("position"); v.push_back("normal"); v.push_back("color"); v.push_back("tex_coord0"); return v; } constexpr static std::string getPath(std::string name, std::string kind){ return [[[NSBundle mainBundle] pathForResource:[NSString stringWithUTF8String:name.c_str()] ofType:[NSString stringWithUTF8String:kind.c_str()]] UTF8String]; } constexpr static std::array from_carray(GLfloat const (& v)[16]){ std::array a; for(int i = 0; i < 16; ++i) a[i] = v[i]; return a; } constexpr static std::array transpose(std::array const & v){ std::array a; for(int i = 0; i < 4; ++i) for(int j = 0; j < 4; ++j) a[i + 4*j] = v[j + 4*i]; return a; } typedef std::array Vertex; typedef std::array Quad; //degenerate int counter; float time; unsigned int width, height; float aspect; unsigned int color_scheme; J::shader noise_shader; J::shader texture_shader; J::shader effect_shader; J::fbo fbo1; J::fbo fbo2; J::interpolator> color_transformation; std::vector quads; App(float w, float h) : counter(0) , time(0) , width(w) , height(h) , aspect(w/h) , color_scheme(0) , noise_shader(getPath("teaShader", "vsh"), getPath("teaShader", "fsh"), get_attributes()) , texture_shader(getPath("textureShader", "vsh"), getPath("textureShader", "fsh"), get_attributes()) , effect_shader(getPath("effectShader", "vsh"), getPath("effectShader", "fsh"), get_attributes()) , fbo1(kFBOWidth, kFBOHeight) , fbo2(kFBOWidth, kFBOHeight) , color_transformation(transpose(from_carray(color_transformations[0])), 1.0) { make_quads(); glEnable(GL_DEPTH_TEST); } ~App() { } void resize(float w, float h) { aspect = std::abs(w/h); } void change_color(){ ++color_scheme %= colors; color_transformation.set_value(transpose(from_carray(color_transformations[color_scheme]))); } void make_quads(){ quads.reserve(number_of_quads); for(int yy = 0; yy < level_height; ++yy){ for(int xx = 0; xx < level_width; ++xx){ if(level[xx + level_width*yy] == 0) continue; const double size = 1.0; double x = xx - (int)level_width/2; double z = -5.0 -level_height + yy; double y = -1.0; Quad q; // deg. q[0][0] = x - size*0.5; q[0][1] = y; q[0][2] = z - size*0.5; q[1][0] = x - size*0.5; q[1][1] = y; q[1][2] = z - size*0.5; // real quad q[2][0] = x - size*0.5; q[2][1] = y; q[2][2] = z - size*0.5; q[3][0] = x - size*0.5; q[3][1] = y; q[3][2] = z + size*0.5; q[4][0] = x + size*0.5; q[4][1] = y; q[4][2] = z - size*0.5; q[5][0] = x + size*0.5; q[5][1] = y; q[5][2] = z + size*0.5; // deg. q[6][0] = x + size*0.5; q[6][1] = y; q[6][2] = z + size*0.5; q[7][0] = x + size*0.5; q[7][1] = y; q[7][2] = z + size*0.5; //double r = rand() / (double) RAND_MAX; //double g = rand() / (double) RAND_MAX; //double b = rand() / (double) RAND_MAX; for(auto& v : q){ v[3] = (x + 2.0) / 5.0; v[4] = 0.5; v[5] = (yy < level_height && yy > level_height - 7)? 1.0 : 0.0; v[6] = 1.0; } quads.push_back(q); } } } void update(float dt) { time += dt; for(auto& q : quads){ for(auto& v : q){ v[2] += dt * 7.0; } if(q[0][2] > 10.0) { for(auto& v : q){ v[2] -= level_height; } } } color_transformation.interpolate(dt); // Update the FBO's here // (can't be done in draw, because of apple's fbo shizzle) fbo1.begin(); scene(); fbo1.end(); fbo2.begin(); effects(fbo1); fbo2.end(); } void draw() { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); texture_shader.begin(); texture_shader.set_uniform("color_transformation", color_transformation, GL_FALSE); texture(texture_shader, fbo2); texture_shader.end(); } void effects(J::fbo& read_fbo){ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); effect_shader.begin(); effect_shader.set_uniform("time", counter * counter * 0.00001f); texture(effect_shader, read_fbo); } void scene(){ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); noise_shader.begin(); GLKMatrix4 p1 = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(80.0f), aspect, 0.01f, 20.0f); GLKMatrix4 p2 = GLKMatrix4MakeLookAt(0.0, 0.0, 9.0, 0.0, -2.0, 0.0, 0.0, 1.0, 0.0); GLKMatrix4 projectionMatrix = GLKMatrix4Multiply(p1, p2); GLKMatrix4 modelViewMatrix = GLKMatrix4Identity; GLKMatrix4 modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); GLKMatrix3 normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); noise_shader.set_uniform("modelViewProjectionMatrix", modelViewProjectionMatrix.m, 0); noise_shader.set_uniform("normalMatrix", normalMatrix.m, 0); noise_shader.set_uniform("time", time); noise_shader.set_attribute("position", 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &quads[0][0][0]); noise_shader.set_attribute("color", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), &quads[0][0][3]); glDrawArrays(GL_TRIANGLE_STRIP, 0, quads.size()*8); } void texture(J::shader const & tex_shader, J::fbo const & read_fbo) { tex_shader.set_texture("tex", GL_TEXTURE_2D, read_fbo.texture_id, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); tex_shader.set_attribute("position", 2, GL_FLOAT, GL_FALSE, 0, &quad[0]); tex_shader.set_attribute("tex_coord0", 2, GL_FLOAT, GL_FALSE, 0, &tex_quad[0]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } }; #endif