Lorenz Attractor with parameters
This commit is contained in:
parent
e79a0ea7b5
commit
1fc2b41631
6 changed files with 53 additions and 149 deletions
78
lib/app.cpp
78
lib/app.cpp
|
@ -6,13 +6,18 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static const std::vector<Vertex> quad = {{
|
||||
// x y z u v
|
||||
{{ 1, -1, 0}, {1, 0}},
|
||||
{{-1, -1, 0}, {0, 0}},
|
||||
{{ 1, 1, 0}, {1, 1}},
|
||||
{{-1, 1, 0}, {0, 1}}
|
||||
}};
|
||||
static std::vector<Vertex> generate_random_points(size_t N){
|
||||
std::vector<Vertex> ret(N);
|
||||
|
||||
const float d = 0.1;
|
||||
for(auto& x : ret){
|
||||
x[0] = d * rand() / float(RAND_MAX);
|
||||
x[1] = d * rand() / float(RAND_MAX);
|
||||
x[2] = d * rand() / float(RAND_MAX);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum {
|
||||
POS_ATTR,
|
||||
|
@ -20,81 +25,47 @@ enum {
|
|||
};
|
||||
|
||||
App::App(GLContext& gl_context)
|
||||
: gl_image1(create_gl_texture(W, H))
|
||||
, gl_image2(create_gl_texture(W, H))
|
||||
, gl_vbo(create_vbo(quad))
|
||||
: gl_vbo(create_vbo(generate_random_points(N)))
|
||||
, gl_vao(create_vao(gl_vbo))
|
||||
, gl_program(create_shader_from_files("Fractal.vsh", "Fractal.fsh"))
|
||||
, cl_context(create_shared_cl_context(gl_context))
|
||||
, cl_device(cl_context.getInfo<CL_CONTEXT_DEVICES>().front())
|
||||
, cl_queue(cl_context, cl_device)
|
||||
, cl_image1(cl_context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, gl_image1)
|
||||
, cl_image2(cl_context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, gl_image2)
|
||||
, cl_buffer(cl_context, 0, gl_vbo.id)
|
||||
, cl_program(create_cl_program("Kernel.cl"))
|
||||
, k_initialize(cl_program, "initialize")
|
||||
, k_hblur(cl_program, "hblur")
|
||||
, k_vblur(cl_program, "vblur")
|
||||
, k_update(cl_program, "update")
|
||||
{
|
||||
cl::checky(k_initialize(cl_queue, W, H, W, H, cl_image1));
|
||||
cl::checky(k_initialize(cl_queue, W, H, W, H, cl_image2));
|
||||
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);
|
||||
}
|
||||
|
||||
void App::draw(){
|
||||
GLuint* gl_images[] = {&gl_image1, &gl_image2};
|
||||
cl::ImageGL* cl_images[] = {&cl_image1, &cl_image2};
|
||||
|
||||
auto dt = 1/60.0;
|
||||
time += dt;
|
||||
if(wait > 0) wait -= dt;
|
||||
|
||||
if(wait <= 0){
|
||||
bool blur = false;
|
||||
if((frame / 200) % 2) blur = true;
|
||||
|
||||
if(blur){
|
||||
frame += 4;
|
||||
cl::checky(k_hblur(cl_queue, W, H, W, H, *cl_images[(frame + 1) % 2], *cl_images[frame % 2]));
|
||||
cl::checky(k_vblur(cl_queue, W, H, W, H, *cl_images[frame % 2], *cl_images[(frame + 1) % 2]));
|
||||
} else {
|
||||
frame++;
|
||||
cl::checky(k_update(cl_queue, W, H, W, H, *cl_images[(frame + 1) % 2], *cl_images[frame % 2]));
|
||||
}
|
||||
k_update(cl_queue, N, p_s, p_r, p_b, p_dt, cl_buffer);
|
||||
}
|
||||
|
||||
cl::checky(cl_queue.finish());
|
||||
|
||||
moggle::gl::clear_color(0.35f, 0.65f, 0.65f, 1.0f);
|
||||
moggle::gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
gl_program.use();
|
||||
|
||||
moggle::gl::bind_texture(GL_TEXTURE_2D, *gl_images[frame % 2]);
|
||||
gl_program.uniform<GLint>("tex").set(0);
|
||||
|
||||
gl_vao.bind();
|
||||
|
||||
moggle::gl::draw_arrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
moggle::gl::draw_arrays(GL_POINTS, 0, N);
|
||||
}
|
||||
|
||||
void App::resize(size_t w, size_t h){
|
||||
wait = 2;
|
||||
wait = 5;
|
||||
|
||||
W = w;
|
||||
H = h;
|
||||
|
||||
gl_image1 = create_gl_texture(W, H);
|
||||
gl_image2 = create_gl_texture(W, H);
|
||||
|
||||
cl_int err = 0;
|
||||
cl_image1 = cl::ImageGL(cl_context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, gl_image1, &err);
|
||||
cl::checky(err);
|
||||
cl_image2 = cl::ImageGL(cl_context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, gl_image2, &err);
|
||||
cl::checky(err);
|
||||
std::cout << cl_image1 << std::endl;
|
||||
|
||||
cl::checky(k_initialize(cl_queue, W, H, W, H, cl_image1));
|
||||
cl::checky(k_initialize(cl_queue, W, H, W, H, cl_image2));
|
||||
}
|
||||
|
||||
moggle::shader_program App::create_shader_from_files(string vertex, string fragment){
|
||||
|
@ -107,7 +78,6 @@ moggle::shader_program App::create_shader_from_files(string vertex, string fragm
|
|||
program.attach(fs);
|
||||
|
||||
program.bind_attribute(POS_ATTR, "position");
|
||||
program.bind_attribute(TEX_ATTR, "tex_coord");
|
||||
|
||||
program.link();
|
||||
|
||||
|
@ -126,10 +96,8 @@ moggle::vao App::create_vao(const moggle::vbo<Vertex>& vbo){
|
|||
vao.bind();
|
||||
|
||||
moggle::gl::enable_vertex_attribute_array(POS_ATTR);
|
||||
moggle::gl::enable_vertex_attribute_array(TEX_ATTR);
|
||||
|
||||
vao.attribute(POS_ATTR, vbo, &Vertex::position);
|
||||
vao.attribute(TEX_ATTR, vbo, &Vertex::tex_coord);
|
||||
vao.attribute(POS_ATTR, vbo);
|
||||
|
||||
return vao;
|
||||
}
|
||||
|
|
21
lib/app.hpp
21
lib/app.hpp
|
@ -8,25 +8,24 @@
|
|||
#include <cl2.hpp>
|
||||
#include <NSGLWrapper.hpp>
|
||||
|
||||
struct Vertex{
|
||||
moggle::vector3<GLfloat> position;
|
||||
moggle::vector2<GLfloat> tex_coord;
|
||||
};
|
||||
using Vertex = moggle::hvector4<GLfloat>;
|
||||
|
||||
struct App {
|
||||
size_t W = 128;
|
||||
size_t H = 128;
|
||||
size_t N = 1 << 20;
|
||||
float time = 0;
|
||||
float wait = 2;
|
||||
size_t frame = 0;
|
||||
float wait = 5;
|
||||
float p_s = 10.962073;
|
||||
float p_r = 31.211250;
|
||||
float p_b = 1.537946;
|
||||
float p_dt = 0.013040;
|
||||
|
||||
App(GLContext & gl_context);
|
||||
void draw();
|
||||
void resize(size_t w, size_t h);
|
||||
|
||||
private:
|
||||
GLuint gl_image1;
|
||||
GLuint gl_image2;
|
||||
moggle::vbo<Vertex> gl_vbo;
|
||||
moggle::vao gl_vao;
|
||||
moggle::shader_program gl_program;
|
||||
|
@ -34,12 +33,8 @@ private:
|
|||
cl::Context cl_context;
|
||||
cl::Device cl_device;
|
||||
cl::CommandQueue cl_queue;
|
||||
cl::ImageGL cl_image1;
|
||||
cl::ImageGL cl_image2;
|
||||
cl::BufferGL cl_buffer;
|
||||
cl::Program cl_program;
|
||||
KernelOp k_initialize;
|
||||
KernelOp k_hblur;
|
||||
KernelOp k_vblur;
|
||||
KernelOp k_update;
|
||||
|
||||
static moggle::shader_program create_shader_from_files(std::string vertex, std::string fragment);
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
#version 330
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec2 tex_coord_int;
|
||||
|
||||
out vec4 fragColor;
|
||||
in float mx;
|
||||
|
||||
void main(){
|
||||
// fragColor = texture(tex, tex_coord_int);
|
||||
fragColor = vec4(0.5) + 0.5*sin(0.1 * texture(tex, tex_coord_int));
|
||||
fragColor = mix(0.7 * vec4(0.3, 0.1, 0.01, 1.0), vec4(0.0, 0.0, 0.4, 1.0), mx);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#version 330
|
||||
|
||||
in vec4 position;
|
||||
in vec2 tex_coord;
|
||||
|
||||
out vec2 tex_coord_int;
|
||||
out float mx;
|
||||
|
||||
void main(){
|
||||
tex_coord_int = tex_coord;
|
||||
gl_Position = position;
|
||||
gl_Position = vec4(1);
|
||||
gl_Position.xy = 0.04*position.xy;
|
||||
mx = cos(0.1*position.z);
|
||||
}
|
||||
|
|
|
@ -1,80 +1,14 @@
|
|||
|
||||
kernel void initialize(size_t width, size_t height, write_only image2d_t output){
|
||||
size_t x = get_global_id(0);
|
||||
size_t y = get_global_id(1);
|
||||
kernel void update(float s, float r, float b, float dt, __global float4* buffer){
|
||||
size_t i = get_global_id(0);
|
||||
|
||||
int2 coord = {x, y};
|
||||
const float xx = x / float(width - 1) - 0.5;
|
||||
const float yy = y / float(height - 1) - 0.5;
|
||||
float4 color = {0.066 * xx, 0.1 * yy, 0.1 * yy * xx, 1};
|
||||
|
||||
write_imagef(output, coord, color);
|
||||
}
|
||||
|
||||
kernel void hblur(size_t width, size_t height, read_only image2d_t input, write_only image2d_t output){
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE
|
||||
| CLK_ADDRESS_NONE
|
||||
| CLK_FILTER_NEAREST;
|
||||
|
||||
float4 c = {0, 0, 0, 0};
|
||||
const int size = 7;
|
||||
float weights[] = {0.25, 0.1, 0.1, 0.1, 0.1, 0.1, 0.25};
|
||||
for(int i = 0; i < size; ++i){
|
||||
int x2 = (x - size/2 + i + width) % width;
|
||||
int2 read = {x2, y};
|
||||
c += read_imagef(input, sampler, read) * weights[i];
|
||||
}
|
||||
|
||||
int2 coord = {x, y};
|
||||
write_imagef(output, coord, c);
|
||||
}
|
||||
|
||||
kernel void vblur(size_t width, size_t height, read_only image2d_t input, write_only image2d_t output){
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE
|
||||
| CLK_ADDRESS_NONE
|
||||
| CLK_FILTER_NEAREST;
|
||||
|
||||
float4 c = {0, 0, 0, 0};
|
||||
int size = 7;
|
||||
float weights[] = {0.25, 0.1, 0.1, 0.1, 0.1, 0.1, 0.25};
|
||||
for(int i = 0; i < size; ++i){
|
||||
int y2 = (y - size/2 + i + height) % height;
|
||||
int2 read = {x, y2};
|
||||
c += read_imagef(input, sampler, read) * weights[i];
|
||||
}
|
||||
|
||||
int2 coord = {x, y};
|
||||
write_imagef(output, coord, c);
|
||||
}
|
||||
|
||||
kernel void update(size_t width, size_t height, read_only image2d_t input, write_only image2d_t output){
|
||||
size_t x = get_global_id(0);
|
||||
size_t y = get_global_id(1);
|
||||
|
||||
int2 coord = {x, y};
|
||||
|
||||
const sampler_t samplerA = CLK_NORMALIZED_COORDS_FALSE
|
||||
| CLK_ADDRESS_NONE
|
||||
| CLK_FILTER_NEAREST;
|
||||
|
||||
const float4 w = read_imagef(input, samplerA, coord);
|
||||
const float4 w = buffer[i];
|
||||
float4 v = w;
|
||||
|
||||
const float s = 9.120836;
|
||||
const float r = 32.799129;
|
||||
const float b = 2.902814;
|
||||
const float dt = 0.019997;
|
||||
|
||||
v.x += dt * s * (w.y - w.x);
|
||||
v.y += dt * (w.x * (r - w.z) - w.y);
|
||||
v.z += dt * (w.x * w.y - b * w.z);
|
||||
|
||||
write_imagef(output, coord, v);
|
||||
buffer[i] = v;
|
||||
}
|
||||
|
||||
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -9,6 +9,7 @@ using namespace std;
|
|||
int main() {
|
||||
NSAppWrapper app;
|
||||
unique_ptr<App> a;
|
||||
|
||||
app.create_window({
|
||||
[&](ContextParameters ctxp){
|
||||
a = make_unique<App>(ctxp.context);
|
||||
|
@ -21,6 +22,17 @@ int main() {
|
|||
}
|
||||
});
|
||||
|
||||
// const float s = 10.962073;
|
||||
// const float r = 31.211250;
|
||||
// const float b = 1.537946;
|
||||
|
||||
app.create_window({{
|
||||
{"s", 10.962073, 9, 13, [&](double x){ a->p_s = x; }},
|
||||
{"r", 31.211250, 30, 32, [&](double x){ a->p_r = 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; }}
|
||||
}});
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue