#include "app.hpp" #include "utils.hpp" #include using namespace std; // implementation follow later static moggle::shader_program create_shader_from_files(std::string vertex, std::string fragment); template static moggle::vbo create_vbo(std::vector const & data); static moggle::vao create_vao(moggle::vbo const & vbo); static moggle::vao create_vao(moggle::vbo const & vbo); static GLuint create_gl_texture(GLsizei width, GLsizei height); static std::vector generate_random_points(size_t N); cl::Context create_shared_cl_context(GLContext & gl_context); std::vector quad = { {{-1, -1}, {0, 0}}, {{ 1, -1}, {1, 0}}, {{-1, 1}, {0, 1}}, {{ 1, 1}, {1, 1}}, }; static const GLsizei FBO_SIZE = 1024; Parameters::Parameters(cl::Context& cl_context, std::initializer_list x) : cl_context(cl_context) , parameters(x) , cl_parameter_buffer(cl_context, CL_MEM_USE_HOST_PTR, parameters.size() * sizeof(float), ¶meters[0]) {} void Parameters::resize(size_t n){ parameters.resize(n); cl_parameter_buffer = cl::Buffer(cl_context, CL_MEM_USE_HOST_PTR, parameters.size() * sizeof(float), ¶meters[0]); } size_t Parameters::size() const { return parameters.size(); } float & Parameters::operator[](size_t n){ return parameters[n]; } float Parameters::operator[](size_t n) const { return parameters[n]; } cl::Buffer const & Parameters::get_cl() const { return cl_parameter_buffer; } App::App(GLContext& gl_context) : gl_vbo(create_vbo(generate_random_points(N))) , gl_vao(create_vao(gl_vbo)) , gl_quad_vbo(create_vbo(quad)) , gl_quad_vao(create_vao(gl_quad_vbo)) , gl_points_program(create_shader_from_files("Points.vsh", "Points.fsh")) , gl_texture_program(create_shader_from_files("Texture.vsh", "Texture.fsh")) , gl_fbo(moggle::create_default_fbo(FBO_SIZE, FBO_SIZE)) , cl_context(create_shared_cl_context(gl_context)) , cl_device(cl_context.getInfo().front()) , cl_queue(cl_context, cl_device) , cl_buffer(cl_context, 0, gl_vbo.get_id()) , cl_program(create_cl_program("Kernel.cl")) , k_update(cl_program, "update") , parameters(cl_context, {10.962073, 31.211250, 1.537946, 0.013040}) { moggle::gl::clear_color(0.0f, 0.0f, 0.0f, 1.0f); moggle::gl::enable(GL_BLEND); moggle::gl::blend_function(GL_ONE, GL_ONE); moggle::gl::blend_equation(GL_FUNC_ADD); moggle::gl::active_texture(GL_TEXTURE0); moggle::gl::texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); moggle::gl::texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } void App::draw(std::function bind, std::function flush){ auto dt = 1/60.0; time += dt; static quaternion speed(1, 0, 0, 0); static int frame = 0; if(frame > 200){ static bool dir = true; frame = 0; if(dir) { speed = quaternion{40.0, 0, 0.1, 0}; dir = false; } else { speed = quaternion{40.0, 0.1, 0, 0}; dir = true; } speed = normalize(speed); } frame++; rotation = speed * rotation; auto const mat = quaternion_to_R3_rotation(normalize(rotation)); // OpenCL update cl::checky(k_update(cl_queue, N, parameters.get_cl(), cl_buffer)); cl::checky(cl_queue.finish()); // OpenGL to fbo gl_fbo.bind(); moggle::gl::viewport(0, 0, FBO_SIZE, FBO_SIZE); if(clear){ gl_fbo.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } gl_points_program.use(); gl_points_program.uniform>("modelmatrix").set(mat); gl_vao.bind(); moggle::gl::draw_arrays(GL_POINTS, 0, N); // Draw fbo bind(); moggle::gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gl_texture_program.use(); gl_fbo.get_texture().bind(GL_TEXTURE_2D); gl_texture_program.uniform("tex").set(0); gl_texture_program.uniform("maxf").set(maxf); gl_texture_program.uniform("gamma").set(gamma); gl_quad_vao.bind(); moggle::gl::draw_arrays(GL_TRIANGLE_STRIP, 0, 4); flush(); } void App::resize(size_t w, size_t h){ W = w; H = h; } cl::Program App::create_cl_program(string file){ cl_int err = 0; // build the program cl::Program cl_program(cl_context, slurp(file), true, &err); cout << cl_program.getBuildInfo(cl_device) << std::endl; cl::checky(err); cout << cl_program << endl; return cl_program; } enum { POS_ATTR, TEX_ATTR }; moggle::shader_program create_shader_from_files(string vertex, string fragment){ moggle::shader_program program; auto vs = moggle::shader::from_file(moggle::shader_type::vertex, vertex); auto fs = moggle::shader::from_file(moggle::shader_type::fragment, fragment); program.attach(vs); program.attach(fs); program.bind_attribute(POS_ATTR, "position"); program.bind_attribute(TEX_ATTR, "tex_coord"); program.link(); return program; } template moggle::vbo create_vbo(const std::vector& data){ moggle::vbo vbo; vbo.bind(GL_ARRAY_BUFFER); vbo.data(data); return vbo; } moggle::vao create_vao(const moggle::vbo& vbo){ moggle::vao vao; vao.bind(); moggle::gl::enable_vertex_attribute_array(POS_ATTR); vao.attribute(POS_ATTR, vbo); return vao; } moggle::vao create_vao(const moggle::vbo& vbo){ moggle::vao vao; vao.bind(); moggle::gl::enable_vertex_attribute_array(POS_ATTR); moggle::gl::enable_vertex_attribute_array(TEX_ATTR); vao.attribute(POS_ATTR, vbo, &Vertex::pos); vao.attribute(TEX_ATTR, vbo, &Vertex::tex); return vao; } GLuint create_gl_texture(GLsizei width, GLsizei height){ GLuint tex = 0; moggle::gl::generate_textures(1, &tex); moggle::gl::bind_texture(GL_TEXTURE_2D, tex); moggle::gl::texture_image_2d(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); return tex; } static std::vector generate_random_points(size_t N){ std::vector ret(N); const auto d = 2.0; for(auto& x : ret){ x[0] = d * rand() / float(RAND_MAX) - 0.5*d; x[1] = d * rand() / float(RAND_MAX) - 0.5*d; x[2] = d * rand() / float(RAND_MAX) - 0.5*d; } return ret; } cl::Context create_shared_cl_context(GLContext& gl_context){ CGLShareGroupObj sharegroup = CGLGetShareGroup(gl_context.ctx); cl_context_properties properties[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)sharegroup, 0 }; cl_int err = 0; cl::Context cl_context(CL_DEVICE_TYPE_CPU, properties, nullptr, nullptr, &err); cl::checky(err); return cl_context; }