Very clean render, with fbo pass, etc etc
This commit is contained in:
parent
1fc2b41631
commit
153bb499a0
10 changed files with 393 additions and 102 deletions
224
lib/app.cpp
224
lib/app.cpp
|
@ -6,28 +6,33 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static std::vector<Vertex> generate_random_points(size_t N){
|
// implementation follow later
|
||||||
std::vector<Vertex> ret(N);
|
static moggle::shader_program create_shader_from_files(std::string vertex, std::string fragment);
|
||||||
|
template <typename T>
|
||||||
|
static moggle::vbo<T> create_vbo(std::vector<T> const & data);
|
||||||
|
static moggle::vao create_vao(moggle::vbo<GLPoint> const & vbo);
|
||||||
|
static moggle::vao create_vao(moggle::vbo<Vertex> const & vbo);
|
||||||
|
static GLuint create_gl_texture(GLsizei width, GLsizei height);
|
||||||
|
static std::vector<GLPoint> generate_random_points(size_t N);
|
||||||
|
cl::Context create_shared_cl_context(GLContext & gl_context);
|
||||||
|
|
||||||
const float d = 0.1;
|
std::vector<Vertex> quad = {
|
||||||
for(auto& x : ret){
|
{{-1, -1}, {0, 0}},
|
||||||
x[0] = d * rand() / float(RAND_MAX);
|
{{ 1, -1}, {1, 0}},
|
||||||
x[1] = d * rand() / float(RAND_MAX);
|
{{-1, 1}, {0, 1}},
|
||||||
x[2] = d * rand() / float(RAND_MAX);
|
{{ 1, 1}, {1, 1}},
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
|
||||||
POS_ATTR,
|
|
||||||
TEX_ATTR
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const GLsizei FBO_SIZE = 1024;
|
||||||
|
|
||||||
App::App(GLContext& gl_context)
|
App::App(GLContext& gl_context)
|
||||||
: gl_vbo(create_vbo(generate_random_points(N)))
|
: gl_vbo(create_vbo(generate_random_points(N)))
|
||||||
, gl_vao(create_vao(gl_vbo))
|
, gl_vao(create_vao(gl_vbo))
|
||||||
, gl_program(create_shader_from_files("Fractal.vsh", "Fractal.fsh"))
|
, 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::fbo::create_default(FBO_SIZE, FBO_SIZE))
|
||||||
, cl_context(create_shared_cl_context(gl_context))
|
, cl_context(create_shared_cl_context(gl_context))
|
||||||
, cl_device(cl_context.getInfo<CL_CONTEXT_DEVICES>().front())
|
, cl_device(cl_context.getInfo<CL_CONTEXT_DEVICES>().front())
|
||||||
, cl_queue(cl_context, cl_device)
|
, cl_queue(cl_context, cl_device)
|
||||||
|
@ -40,94 +45,49 @@ App::App(GLContext& gl_context)
|
||||||
moggle::gl::enable(GL_BLEND);
|
moggle::gl::enable(GL_BLEND);
|
||||||
moggle::gl::blend_function(GL_ONE, GL_ONE);
|
moggle::gl::blend_function(GL_ONE, GL_ONE);
|
||||||
moggle::gl::blend_equation(GL_FUNC_ADD);
|
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(){
|
void App::draw(std::function<void(void)> bind, std::function<void(void)> flush){
|
||||||
auto dt = 1/60.0;
|
auto dt = 1/60.0;
|
||||||
time += dt;
|
time += dt;
|
||||||
if(wait > 0) wait -= dt;
|
|
||||||
|
|
||||||
if(wait <= 0){
|
|
||||||
k_update(cl_queue, N, p_s, p_r, p_b, p_dt, cl_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// OpenCL update
|
||||||
|
k_update(cl_queue, N, p_s, p_r, p_b, p_dt, cl_buffer);
|
||||||
cl::checky(cl_queue.finish());
|
cl::checky(cl_queue.finish());
|
||||||
|
|
||||||
|
// OpenGL to fbo
|
||||||
|
gl_fbo.bind();
|
||||||
|
moggle::gl::viewport(0, 0, FBO_SIZE, FBO_SIZE);
|
||||||
|
|
||||||
|
gl_points_program.use();
|
||||||
|
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);
|
moggle::gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
gl_program.use();
|
gl_texture_program.use();
|
||||||
gl_vao.bind();
|
|
||||||
|
|
||||||
moggle::gl::draw_arrays(GL_POINTS, 0, N);
|
gl_fbo.get_texture().bind(GL_TEXTURE_2D);
|
||||||
|
gl_texture_program.uniform<GLint>("tex").set(0);
|
||||||
|
gl_texture_program.uniform<GLfloat>("maxf").set(maxf);
|
||||||
|
|
||||||
|
gl_quad_vao.bind();
|
||||||
|
moggle::gl::draw_arrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::resize(size_t w, size_t h){
|
void App::resize(size_t w, size_t h){
|
||||||
wait = 5;
|
|
||||||
|
|
||||||
W = w;
|
W = w;
|
||||||
H = h;
|
H = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
moggle::shader_program App::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.link();
|
|
||||||
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
moggle::vbo<Vertex> App::create_vbo(const std::vector<Vertex>& data){
|
|
||||||
moggle::vbo<Vertex> vbo;
|
|
||||||
vbo.bind(GL_ARRAY_BUFFER);
|
|
||||||
vbo.data(data);
|
|
||||||
return vbo;
|
|
||||||
}
|
|
||||||
|
|
||||||
moggle::vao App::create_vao(const moggle::vbo<Vertex>& vbo){
|
|
||||||
moggle::vao vao;
|
|
||||||
vao.bind();
|
|
||||||
|
|
||||||
moggle::gl::enable_vertex_attribute_array(POS_ATTR);
|
|
||||||
|
|
||||||
vao.attribute(POS_ATTR, vbo);
|
|
||||||
|
|
||||||
return vao;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint App::create_gl_texture(GLsizei width, GLsizei height){
|
|
||||||
GLuint tex = 0;
|
|
||||||
moggle::gl::active_texture(GL_TEXTURE0);
|
|
||||||
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);
|
|
||||||
moggle::gl::texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
moggle::gl::texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl::Context App::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl::Program App::create_cl_program(string file){
|
cl::Program App::create_cl_program(string file){
|
||||||
cl_int err = 0;
|
cl_int err = 0;
|
||||||
|
|
||||||
|
@ -140,3 +100,93 @@ cl::Program App::create_cl_program(string file){
|
||||||
|
|
||||||
return cl_program;
|
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 <typename T>
|
||||||
|
moggle::vbo<T> create_vbo(const std::vector<T>& data){
|
||||||
|
moggle::vbo<T> vbo;
|
||||||
|
vbo.bind(GL_ARRAY_BUFFER);
|
||||||
|
vbo.data(data);
|
||||||
|
return vbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
moggle::vao create_vao(const moggle::vbo<GLPoint>& 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<Vertex>& 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<GLPoint> generate_random_points(size_t N){
|
||||||
|
std::vector<GLPoint> 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;
|
||||||
|
}
|
||||||
|
|
29
lib/app.hpp
29
lib/app.hpp
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "fbo.hpp"
|
||||||
#include <moggle/core/gl.hpp>
|
#include <moggle/core/gl.hpp>
|
||||||
#include <moggle/core/shader.hpp>
|
#include <moggle/core/shader.hpp>
|
||||||
#include <moggle/core/vao.hpp>
|
#include <moggle/core/vao.hpp>
|
||||||
|
@ -8,27 +9,38 @@
|
||||||
#include <cl2.hpp>
|
#include <cl2.hpp>
|
||||||
#include <NSGLWrapper.hpp>
|
#include <NSGLWrapper.hpp>
|
||||||
|
|
||||||
using Vertex = moggle::hvector4<GLfloat>;
|
// Used for the bare points
|
||||||
|
using GLPoint = moggle::hvector4<GLfloat>;
|
||||||
|
|
||||||
|
// Used for rendering a textured quad
|
||||||
|
struct Vertex {
|
||||||
|
moggle::vector2<GLfloat> pos;
|
||||||
|
moggle::vector2<GLfloat> tex;
|
||||||
|
};
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
size_t W = 128;
|
size_t W = 128;
|
||||||
size_t H = 128;
|
size_t H = 128;
|
||||||
size_t N = 1 << 20;
|
size_t N = 1 << 18;
|
||||||
float time = 0;
|
float time = 0;
|
||||||
float wait = 5;
|
|
||||||
float p_s = 10.962073;
|
float p_s = 10.962073;
|
||||||
float p_r = 31.211250;
|
float p_r = 31.211250;
|
||||||
float p_b = 1.537946;
|
float p_b = 1.537946;
|
||||||
float p_dt = 0.013040;
|
float p_dt = 0.013040;
|
||||||
|
float maxf = 500;
|
||||||
|
|
||||||
App(GLContext & gl_context);
|
App(GLContext & gl_context);
|
||||||
void draw();
|
void draw(std::function<void(void)> bind, std::function<void(void)> flush);
|
||||||
void resize(size_t w, size_t h);
|
void resize(size_t w, size_t h);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
moggle::vbo<Vertex> gl_vbo;
|
moggle::vbo<GLPoint> gl_vbo;
|
||||||
moggle::vao gl_vao;
|
moggle::vao gl_vao;
|
||||||
moggle::shader_program gl_program;
|
moggle::vbo<Vertex> gl_quad_vbo;
|
||||||
|
moggle::vao gl_quad_vao;
|
||||||
|
moggle::shader_program gl_points_program;
|
||||||
|
moggle::shader_program gl_texture_program;
|
||||||
|
moggle::fbo gl_fbo;
|
||||||
|
|
||||||
cl::Context cl_context;
|
cl::Context cl_context;
|
||||||
cl::Device cl_device;
|
cl::Device cl_device;
|
||||||
|
@ -37,10 +49,5 @@ private:
|
||||||
cl::Program cl_program;
|
cl::Program cl_program;
|
||||||
KernelOp k_update;
|
KernelOp k_update;
|
||||||
|
|
||||||
static moggle::shader_program create_shader_from_files(std::string vertex, std::string fragment);
|
|
||||||
static moggle::vbo<Vertex> create_vbo(std::vector<Vertex> const & data);
|
|
||||||
static moggle::vao create_vao(moggle::vbo<Vertex> const & vbo);
|
|
||||||
static GLuint create_gl_texture(GLsizei width, GLsizei height);
|
|
||||||
static cl::Context create_shared_cl_context(GLContext & gl_context);
|
|
||||||
cl::Program create_cl_program(std::string file);
|
cl::Program create_cl_program(std::string file);
|
||||||
};
|
};
|
||||||
|
|
91
lib/fbo.hpp
Normal file
91
lib/fbo.hpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <moggle/core/gl.hpp>
|
||||||
|
#include "renderbuffer.hpp"
|
||||||
|
#include "texture.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One can attach either an external renderbuffer/texture, or move one into fbo
|
||||||
|
* In the latter case, the fbo will own the renderbuffer/texture
|
||||||
|
*
|
||||||
|
* Attachment can be one of: GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, or GL_STENCIL_ATTACHMENT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace moggle {
|
||||||
|
|
||||||
|
struct fbo {
|
||||||
|
explicit fbo(bool create_now = false) {
|
||||||
|
if(create_now) create();
|
||||||
|
}
|
||||||
|
|
||||||
|
~fbo() { destroy(); }
|
||||||
|
|
||||||
|
fbo(fbo const &) = delete;
|
||||||
|
fbo & operator=(fbo const&) = delete;
|
||||||
|
|
||||||
|
fbo(fbo && r) : id(r.id) { r.id = 0; }
|
||||||
|
fbo & operator=(fbo && r) { std::swap(id, r.id); return *this; }
|
||||||
|
|
||||||
|
bool created() const { return id; }
|
||||||
|
explicit operator bool() const { return created(); }
|
||||||
|
|
||||||
|
void create(){ if(!id) gl::generate_framebuffers(1, &id); }
|
||||||
|
void destroy(){ gl::delete_renderbuffers(1, &id); id = 0; }
|
||||||
|
|
||||||
|
void bind() {
|
||||||
|
create();
|
||||||
|
gl::bind_framebuffer(GL_FRAMEBUFFER, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint get_id() const {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only well defined if the fbo owns the texture
|
||||||
|
texture & get_texture() {
|
||||||
|
return textures.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach(GLenum attachment, renderbuffer const & rb){
|
||||||
|
bind();
|
||||||
|
gl::framebuffer_renderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rb.get_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach(GLenum attachment, renderbuffer && rb){
|
||||||
|
renderbuffers.push_back(std::move(rb));
|
||||||
|
attach(attachment, renderbuffers.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach(GLenum attachment, GLenum textarget, texture const & t){
|
||||||
|
bind();
|
||||||
|
gl::framebuffer_texture_2d(GL_FRAMEBUFFER, attachment, textarget, t.get_id(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach(GLenum attachment, GLenum textarget, texture && t){
|
||||||
|
textures.push_back(std::move(t));
|
||||||
|
attach(attachment, textarget, textures.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(GLenum bufferbits){
|
||||||
|
bind();
|
||||||
|
gl::clear(bufferbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fbo create_default(GLsizei width, GLsizei height){
|
||||||
|
fbo f;
|
||||||
|
f.attach(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture::create(width, height, GL_RGBA32F));
|
||||||
|
f.attach(GL_DEPTH_ATTACHMENT, renderbuffer::create(width, height, 1, GL_DEPTH_COMPONENT16));
|
||||||
|
f.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<renderbuffer> renderbuffers;
|
||||||
|
std::vector<texture> textures;
|
||||||
|
|
||||||
|
GLuint id = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
57
lib/renderbuffer.hpp
Normal file
57
lib/renderbuffer.hpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <moggle/core/gl.hpp>
|
||||||
|
|
||||||
|
namespace moggle {
|
||||||
|
|
||||||
|
struct renderbuffer {
|
||||||
|
explicit renderbuffer(bool create_now = false) {
|
||||||
|
if(create_now) create();
|
||||||
|
}
|
||||||
|
|
||||||
|
~renderbuffer() { destroy(); }
|
||||||
|
|
||||||
|
renderbuffer(renderbuffer const &) = delete;
|
||||||
|
renderbuffer & operator=(renderbuffer const&) = delete;
|
||||||
|
|
||||||
|
renderbuffer(renderbuffer && r) : id(r.id) { r.id = 0; }
|
||||||
|
renderbuffer & operator=(renderbuffer && r) { std::swap(id, r.id); return *this; }
|
||||||
|
|
||||||
|
bool created() const { return id; }
|
||||||
|
explicit operator bool() const { return created(); }
|
||||||
|
|
||||||
|
void create(){ if(!id) gl::generate_renderbuffers(1, &id); }
|
||||||
|
void destroy(){ gl::delete_renderbuffers(1, &id); id = 0; }
|
||||||
|
|
||||||
|
void bind() {
|
||||||
|
create();
|
||||||
|
gl::bind_renderbuffer(GL_RENDERBUFFER, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint get_id() const {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void storage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height){
|
||||||
|
bind();
|
||||||
|
gl::renderbuffer_storage(target, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void storage_multisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height){
|
||||||
|
bind();
|
||||||
|
// TODO: wrap this call
|
||||||
|
glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static renderbuffer create(GLsizei width, GLsizei height, GLsizei samples = 1, GLenum format = GL_RGBA4){
|
||||||
|
renderbuffer r;
|
||||||
|
if(samples <= 1) r.storage(GL_RENDERBUFFER, format, width, height);
|
||||||
|
else r.storage_multisample(GL_RENDERBUFFER, samples, format, width, height);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint id = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
62
lib/texture.hpp
Normal file
62
lib/texture.hpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <moggle/core/gl.hpp>
|
||||||
|
#include <moggle/core/gl_type_traits.hpp>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE:
|
||||||
|
* in glTexImage2D, border MUST be 0, so this parameter is left out in this interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace moggle {
|
||||||
|
|
||||||
|
struct texture {
|
||||||
|
explicit texture(bool create_now = false) {
|
||||||
|
if(create_now) create();
|
||||||
|
}
|
||||||
|
|
||||||
|
~texture() { destroy(); }
|
||||||
|
|
||||||
|
texture(texture const &) = delete;
|
||||||
|
texture & operator=(texture const&) = delete;
|
||||||
|
|
||||||
|
texture(texture && t) : id(t.id) { t.id = 0; }
|
||||||
|
texture & operator=(texture && t) { std::swap(id, t.id); return *this; }
|
||||||
|
|
||||||
|
bool created() const { return id; }
|
||||||
|
explicit operator bool() const { return created(); }
|
||||||
|
|
||||||
|
void create(){ if(!id) gl::generate_textures(1, &id); }
|
||||||
|
void destroy(){ gl::delete_textures(1, &id); id = 0; }
|
||||||
|
|
||||||
|
void bind(GLenum target) {
|
||||||
|
create();
|
||||||
|
gl::bind_texture(target, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint get_id() const { return id; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void image_2d(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLenum format, const T * data){
|
||||||
|
bind(target);
|
||||||
|
auto type = gl_type_traits<T>::gl_constant;
|
||||||
|
gl::texture_image_2d(target, level, internalformat, width, height, 0, format, type, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_2d(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, std::nullptr_t){
|
||||||
|
bind(target);
|
||||||
|
gl::texture_image_2d(target, level, internalformat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! creates empty texture
|
||||||
|
static texture create(GLsizei width, GLsizei height, GLint internalformat = GL_RGBA, GLenum target = GL_TEXTURE_2D){
|
||||||
|
texture t;
|
||||||
|
t.image_2d(target, 0, internalformat, width, height, nullptr);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint id = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -6,5 +6,5 @@ out float mx;
|
||||||
void main(){
|
void main(){
|
||||||
gl_Position = vec4(1);
|
gl_Position = vec4(1);
|
||||||
gl_Position.xy = 0.04*position.xy;
|
gl_Position.xy = 0.04*position.xy;
|
||||||
mx = cos(0.1*position.z);
|
mx = cos(0.1337*position.z);
|
||||||
}
|
}
|
12
resources/Texture.fsh
Normal file
12
resources/Texture.fsh
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform float maxf;
|
||||||
|
|
||||||
|
in vec2 tex_coord_;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
fragColor = sqrt(texture(tex, tex_coord_) / maxf);
|
||||||
|
}
|
11
resources/Texture.vsh
Normal file
11
resources/Texture.vsh
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec4 position;
|
||||||
|
in vec2 tex_coord;
|
||||||
|
|
||||||
|
out vec2 tex_coord_;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
gl_Position = position;
|
||||||
|
tex_coord_ = tex_coord;
|
||||||
|
}
|
|
@ -14,8 +14,8 @@ int main() {
|
||||||
[&](ContextParameters ctxp){
|
[&](ContextParameters ctxp){
|
||||||
a = make_unique<App>(ctxp.context);
|
a = make_unique<App>(ctxp.context);
|
||||||
},
|
},
|
||||||
[&](ContextParameters){
|
[&](ContextParameters ctxp){
|
||||||
a->draw();
|
a->draw(ctxp.bind_framebuffer, ctxp.flush_drawable);
|
||||||
},
|
},
|
||||||
[&](ContextParameters, CGFloat w, CGFloat h){
|
[&](ContextParameters, CGFloat w, CGFloat h){
|
||||||
a->resize(size_t(floor(w)), size_t(floor(h)));
|
a->resize(size_t(floor(w)), size_t(floor(h)));
|
||||||
|
@ -30,7 +30,8 @@ int main() {
|
||||||
{"s", 10.962073, 9, 13, [&](double x){ a->p_s = x; }},
|
{"s", 10.962073, 9, 13, [&](double x){ a->p_s = x; }},
|
||||||
{"r", 31.211250, 30, 32, [&](double x){ a->p_r = x; }},
|
{"r", 31.211250, 30, 32, [&](double x){ a->p_r = x; }},
|
||||||
{"b", 1.537946, 0.0001, 3, [&](double x){ a->p_b = x; }},
|
{"b", 1.537946, 0.0001, 3, [&](double x){ a->p_b = x; }},
|
||||||
{"dt", 0.013040, 0.0001, 0.03, [&](double x){ a->p_dt = x; }}
|
{"dt", 0.013040, 0.0001, 0.03, [&](double x){ a->p_dt = x; }},
|
||||||
|
{"max", 500, 0.1, 50000, [&](double x){ a->maxf = x; }},
|
||||||
}});
|
}});
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
|
|
Reference in a new issue