From cbb4612981182d6d9a1f3645899647705c62e980 Mon Sep 17 00:00:00 2001 From: Pavel V Date: Wed, 15 Nov 2023 10:27:49 +0300 Subject: [PATCH] ugly attempt to refactor rendering backend --- CMakeLists.txt | 15 +++-- acidworm.cpp | 2 +- art.cpp | 83 +++-------------------- art.hpp | 54 ++++++--------- attractor.cpp | 9 ++- attractor.h | 3 +- easel.h | 83 +++++++++++++++++++++++ easelplane.cpp | 101 ++++++++++++++++++++++++++++ easelplane.h | 34 ++++++++++ easelvertex.cpp | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ easelvertex.h | 26 ++++++++ main.cpp | 158 ++----------------------------------------- mtron.cpp | 1 + onepixel.h | 4 +- rdbomb.cpp | 1 + thornbird.h | 3 - 16 files changed, 476 insertions(+), 274 deletions(-) create mode 100644 easel.h create mode 100644 easelplane.cpp create mode 100644 easelplane.h create mode 100644 easelvertex.cpp create mode 100644 easelvertex.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 679d0f0..944ab41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,8 @@ add_library(clouds OBJECT artfactory.cpp settings.cpp imgui_elements.cpp - vertexbuffer.cpp + easelplane.cpp + easelvertex.cpp random.c cloudlife.cpp mtron.cpp @@ -83,13 +84,13 @@ target_link_libraries(clouds IMGUI glfw GL colormap) #set_property(TARGET clouds PROPERTY CXX_STANDARD 17) add_executable(cloudlife main.cpp $) -add_executable(cloudtest test.cpp $) +#add_executable(cloudtest test.cpp $) target_link_libraries(cloudlife IMGUI ${GLFW3_LIBRARY} ${OPENGL_LIBRARIES} colormap) -target_link_libraries(cloudtest IMGUI ${GLFW3_LIBRARY} ${OPENGL_LIBRARIES} colormap) +#target_link_libraries(cloudtest IMGUI ${GLFW3_LIBRARY} ${OPENGL_LIBRARIES} colormap) set_target_properties(cloudlife PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set_target_properties(cloudtest PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +#set_target_properties(cloudtest PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -include(CTest) +#include(CTest) -add_test(NAME CloudTest1 COMMAND cloudtest -f 1024 -i 2 -r 512) -add_test(NAME CloudTest2 COMMAND cloudtest -f 32 -i 8 -r 16) +#add_test(NAME CloudTest1 COMMAND cloudtest -f 1024 -i 2 -r 512) +#add_test(NAME CloudTest2 COMMAND cloudtest -f 32 -i 8 -r 16) diff --git a/acidworm.cpp b/acidworm.cpp index f6b5958..6385c20 100644 --- a/acidworm.cpp +++ b/acidworm.cpp @@ -380,7 +380,7 @@ void AcidWorm::resize(int _w, int _h) { //mpp.resize(1024); _ip.resize(max_x * max_y); ip = _ip.data(); ref.resize(max_y); - fill0(ref); + #warning "fill0(ref);" for (int n = 0; n < max_y; ++n) { ref[n] = ip; diff --git a/art.cpp b/art.cpp index ee23c1f..82b6023 100644 --- a/art.cpp +++ b/art.cpp @@ -8,96 +8,32 @@ const char* Art::name() { } void Art::resized(int _w, int _h) { - if (use_vertex_buffer) - vb = std::make_unique(vertex_buffer_maximum()); - else - if (use_pixel_buffer) - pb = std::make_unique(); - tex_w = _w, tex_h = _h; frame_number = 0; + easel->set_window_size(_w, _h); resize(_w, _h); } bool Art::gui() { - if (ImGui::Checkbox("Force use vertex buffer", &use_vertex_buffer)) { - if (use_vertex_buffer) - vb = std::make_unique(vertex_buffer_maximum()); - else - vb.reset(); - } - - if (!use_vertex_buffer) - if (ImGui::Checkbox("Force use pixel buffer", &use_pixel_buffer)) { - if (use_pixel_buffer) - pb = std::make_unique(); - else - pb.reset(); - } - - if (pb) - ScrollableSliderUInt("Max pixels", &pixel_buffer_maximum, 1, pixel_buffer_maximum_max, "%d", pixel_buffer_maximum/16); - if (vb) { - if (ScrollableSliderUInt("Max vertex", &vertex_buffer_maximum_k, 1, 1024*32, "%d", 32)) { - vb = std::make_unique(vertex_buffer_maximum()); - } - ScrollableSliderUInt("Frame vertex target", &frame_vertex_target_k, 1, 1024, "%d", 8); - - } + easel->gui(); bool resize_pbo = render_gui(); - ImGui::Text("pixels drawn %d, discarded %d", - pixels_drawn, pixels_discarded); - - if (pb) - ImGui::Text("pixel_buffer_size %ld", - pb->buffer.size()); - if (vb) - ImGui::Text("total vertecies %d", - vb->total_vertices); + //ImGui::Text("pixels drawn %d, discarded %d", + // pixels_drawn, pixels_discarded); return resize_pbo; } void Art::draw(uint32_t* p) { bool direct = render(p); - if (vb) - vb->draw(); - else - if (pb) { - pb->erase_old(pixel_buffer_maximum); - render_pixel_buffer(p); - } else if (!direct) { - std::copy(m_pixels.begin(), m_pixels.end(), p); - } -} - -void Art::drawdot(uint32_t* screen, uint32_t x, uint32_t y, uint32_t c) { - if (x >= tex_w || y >= tex_h) { - ++pixels_discarded; - return; - } - - if (vb) - vb->adot((float)x/tex_w-.5, (float)y/tex_h-.5); - else - if (pb) - pb->append({x, y, c}); - else - really_drawdot(screen, x, y, c); - - ++pixels_drawn; + easel->render(); } void Art::clear() { - fill0(m_pixels); - pixels_drawn = 0; - pixels_discarded = 0; - if (vb) - vb->clear(); + easel->clear(); } - +/* void Art::render_pixel_buffer(uint32_t* screen) { std::fill_n(screen, w*h, 0); #if 1 @@ -110,12 +46,12 @@ void Art::render_pixel_buffer(uint32_t* screen) { drawdot(screen, p.x, p.y, p.color); #endif } - +*/ void Art::default_resize(int _w, int _h) { w = _w; h = _h; //data = (uint8_t *)xrealloc(data, w*h*sizeof(uint32_t)); - m_pixels.resize(w*h); + //m_pixels.resize(w*h); clear(); /* TODO: fill square in drawdot() if pscale > 1 pscale = 1; @@ -124,4 +60,3 @@ void Art::default_resize(int _w, int _h) { */ } - diff --git a/art.hpp b/art.hpp index 069b149..39aecb1 100644 --- a/art.hpp +++ b/art.hpp @@ -7,8 +7,8 @@ #include -#include "pixelbuffer.h" -#include "vertexbuffer.h" +#include "easelplane.h" +#include "easelvertex.h" template @@ -27,7 +27,11 @@ fill0(T &container) { class Art { public: Art(std::string _name) - : m_name(_name) {} + : m_name(_name) + { + if (!easel) + easel = std::make_unique(); + } const char * name(); /* called when main window is resized and if reinit needed. @@ -44,22 +48,18 @@ class Art { virtual void load(std::string json) {}; virtual std::string save() { return ""; }; - void drawdot(uint32_t x, uint32_t y, double o, uint32_t c) { - drawdot(x, y, c | ((unsigned)(0xff*o)<<24)); + void drawdot(uint32_t *p, int32_t x, int32_t y, double o, uint32_t c) { + drawdot(x, y, o, c); } - void drawdot(uint32_t x, uint32_t y, uint32_t c) { - drawdot(data(), x, y, c); + void drawdot(int32_t x, int32_t y, double o, uint32_t c) { + drawdot(x, y, c | ((unsigned)(0xff*o)<<24)); } - void drawdot(uint32_t *screen, uint32_t x, uint32_t y, double o, uint32_t c) { - drawdot(screen, x, y, c | ((unsigned)(0xff*o)<<24)); + void drawdot(uint32_t *p, int32_t x, int32_t y, uint32_t c) { + drawdot(x,y,c); } - /* don't really draws a dot if pixel buffer is used */ - void drawdot(uint32_t *screen, uint32_t x, uint32_t y, uint32_t c); - - void really_drawdot(uint32_t *screen, uint32_t x, uint32_t y, uint32_t c) { - //printf("%x ", c); - screen[ y*tex_w + x ] = c; + void drawdot(int32_t x, int32_t y, uint32_t c) { + easel->drawdot(x,y,c); } /* deprecated? */ @@ -71,15 +71,6 @@ class Art { unsigned frame_number = 0, clear_every = 0, max_kframes = 0; unsigned pixel_buffer_maximum = 1024*10, pixel_buffer_maximum_max = 1024*1024; - unsigned vertex_buffer_maximum_k = 1024; - unsigned frame_vertex_target_k = 16; - - unsigned vertex_buffer_maximum() const { - return vertex_buffer_maximum_k * 1024; - } - unsigned frame_vertex_target() const { - return frame_vertex_target_k * 1024; - } /* clears m_pixels */ @@ -95,18 +86,17 @@ class Art { void render_pixel_buffer(uint32_t *screen); - uint32_t *data() { return m_pixels.data(); } + //uint32_t *data() { return m_pixels.data(); } protected: - std::unique_ptr pb; - std::unique_ptr vb; - bool use_pixel_buffer = false; - bool use_vertex_buffer = true; - unsigned pixels_drawn = 0; - unsigned pixels_discarded = 0; void default_resize(int _w, int _h); + + std::unique_ptr easel; int w, h; - std::vector m_pixels; std::string m_name; + + EaselPlane* plane() const { + return dynamic_cast(easel.get()); + } }; diff --git a/attractor.cpp b/attractor.cpp index c75357e..59e7dba 100644 --- a/attractor.cpp +++ b/attractor.cpp @@ -43,7 +43,9 @@ bool Attractor::render(uint32_t *p) int x, y; double oldi, oldj; - for (int i=0; i < frame_vertex_target() && count < vertex_buffer_maximum(); ++i, ++count) { + auto ftarget = easel->frame_vertex_target(); + auto vbmax = easel->vertex_buffer_maximum(); + for (int i=0; i < ftarget && count < vbmax; ++i, ++count) { oldj = aj; oldi = ai + inc; aj = a - ai; @@ -54,7 +56,8 @@ bool Attractor::render(uint32_t *p) x = w/2 + (int) (ai + aj); y = h/2 - (int) (ai - aj); - drawdot(x, y, pal.get_color((vertex_buffer_maximum() - count)>>2)); + drawdot(x, y, 0); + //drawdot(x, y, pal.get_color((vertex_buffer_maximum() - count)>>2)); //pb->adot((float)x/w-.5, (float)y/h-.5); } @@ -96,7 +99,7 @@ bool Attractor::render_gui () void Attractor::resize(int _w, int _h) { default_resize(_w, _h); - pal.rescale(vertex_buffer_maximum() >> 2); + pal.rescale(easel->vertex_buffer_maximum() >> 2); count = 0; //clear(); diff --git a/attractor.h b/attractor.h index 482d425..270cdf7 100644 --- a/attractor.h +++ b/attractor.h @@ -10,8 +10,9 @@ class Attractor : public Art { public: Attractor() : Art("strange attractors") { + easel = std::make_unique(); //use_pixel_buffer = true; - pixel_buffer_maximum = 1024*1024; + //pixel_buffer_maximum = 1024*1024; } private: diff --git a/easel.h b/easel.h new file mode 100644 index 0000000..80330d0 --- /dev/null +++ b/easel.h @@ -0,0 +1,83 @@ +#pragma once +#include +//#include +#include + +#include "imgui.h" + +#define GL_GLEXT_PROTOTYPES 1 +#define GL3_PROTOTYPES 1 +#include // Will drag system OpenGL headers + + +#if 0 +// attempt to make drawdot call not virtual +enum class Etype { PLANE, PIXEL, VERTEX }; +template +class Easel { +public: +}; +#endif + +class Easel { +public: + Easel() = default; + virtual ~Easel() = default; + + // every drawdot call is vertual now :( + virtual void drawdot(int32_t x, int32_t y, uint32_t c) = 0; + + virtual void render() = 0; + virtual void clear() {}; + virtual void gui() {}; + virtual void reset() {}; + + + // TODO: ugly pieces from vertex easel, move to a better place + unsigned frame_vertex_target_k = 128; + unsigned frame_vertex_target() const { + return frame_vertex_target_k * 1024; + } + + unsigned vertex_buffer_maximum_k = 1024*16; + unsigned vertex_buffer_maximum() const { + return vertex_buffer_maximum_k * 1024; + } + + + // TODO: ugly pieces from plane easel, move to a better place + void set_window_size(int _w, int _h) { + ww = _w; wh = _h; + w = _w; h = _h; // TODO: or do set_texture_size() in Art::default_resize? + reset(); + } + void set_texture_size(int _w, int _h) { + w = _w; h = _h; + reset(); + } + int w, h; + int ww, wh; +}; + + +// deprecated +/* +class EaselPixel : public Easel { +public: + + EaselPixel(unsigned max_vertices); + ~EaselPixel(); + + void append(Pixel && p); + + virtual void render() override; + virtual void clear() override; + virtual void gui() override; + +private: + unsigned pixels_drawn = 0; + unsigned pixels_discarded = 0; + std::deque buffer; +}; +*/ + diff --git a/easelplane.cpp b/easelplane.cpp new file mode 100644 index 0000000..be6fe38 --- /dev/null +++ b/easelplane.cpp @@ -0,0 +1,101 @@ +#include "easelplane.h" + +#include + +// GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT, GL_REPEAT, GL_MIRROR_CLAMP_TO_EDGE + +int EaselPlane::texture_size() { + return w * h * sizeof(pixel_t); +} + +void EaselPlane::make_pbos() { + image_data_vector.resize(texture_size()); + image_data = image_data_vector.data(); + + // AUTHOR: Song Ho Ahn (song.ahn@gmail.com) + // http://www.songho.ca/opengl/gl_pbo.html + glGenTextures(1, &image_texture); + glBindTexture(GL_TEXTURE_2D, image_texture); + 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_REPEAT); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, + 0, GL_RGBA, w, h, + 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image_data); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenBuffers(2, pboIds); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[0]); + glBufferData(GL_PIXEL_UNPACK_BUFFER, texture_size(), + 0, GL_STREAM_DRAW); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[1]); + glBufferData(GL_PIXEL_UNPACK_BUFFER, texture_size(), + 0, GL_STREAM_DRAW); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); +} + +void EaselPlane::destroy_pbos() { + if (image_data_vector.size() == 0) + return; + + glDeleteTextures(1, &image_texture); + glDeleteBuffers(2, pboIds); +} + + +EaselPlane::EaselPlane() +{ + // make_pbos() done in reset() after resize() +} + +EaselPlane::~EaselPlane() { + destroy_pbos(); +} + +void EaselPlane::reset() { + m_plane.resize(w*h); + destroy_pbos(); + make_pbos(); +} + +void EaselPlane::render() { + int nexti = pbo_index; + pbo_index = pbo_index ? 0 : 1; + glBindTexture(GL_TEXTURE_2D, image_texture); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[pbo_index]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0); + //glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[nexti]); + glBufferData(GL_PIXEL_UNPACK_BUFFER, texture_size(), + 0, GL_STREAM_DRAW); + uint32_t* ptr = (uint32_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + assert(ptr); + //art->draw(ptr); + std::copy(m_plane.begin(), m_plane.end(), ptr); + + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + ImGui::GetBackgroundDrawList()->AddImage((void*)(intptr_t)image_texture, + ImVec2(0, 0), ImVec2(ww, wh), + ImVec2(0, 0), ImVec2((float)ww/w, (float)wh/h)); +} + + +void EaselPlane::drawdot(int32_t x, int32_t y, uint32_t c) { + if (x >= w || y >= h) { + ++pixels_discarded; + return; + } + + m_plane[ y*w + x ] = c; + ++pixels_drawn; +} diff --git a/easelplane.h b/easelplane.h new file mode 100644 index 0000000..12e05d2 --- /dev/null +++ b/easelplane.h @@ -0,0 +1,34 @@ +#pragma once +#include "easel.h" + +class EaselPlane : public Easel { +public: + EaselPlane(); + ~EaselPlane(); + + //void append(Pixel && p); + void drawdot(int32_t x, int32_t y, uint32_t c) override; + + virtual void render() override; + //virtual void clear() override; + //virtual void gui() override; + virtual void reset() override; + +private: + unsigned pixels_drawn = 0; + unsigned pixels_discarded = 0; + + void make_pbos(); + void destroy_pbos(); + int texture_size(); + + typedef uint32_t pixel_t; + pixel_t *image_data = NULL; + std::vector image_data_vector; + + GLuint image_texture; + GLuint pboIds[2]; + int pbo_index = 0; + std::vector m_plane; +}; + diff --git a/easelvertex.cpp b/easelvertex.cpp new file mode 100644 index 0000000..0830393 --- /dev/null +++ b/easelvertex.cpp @@ -0,0 +1,173 @@ +#include "easelvertex.h" + +#include "imgui_elements.h" + +#include +#include + + + + +const char* vertexShaderSource = R"( + #version 330 core + layout (location = 0) in vec3 aPos; + void main() + { + gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); + } +)"; + +const char* fragmentShaderSource = R"( + #version 330 core + out vec4 fragColor; + uniform vec4 vertexColor; + void main() + { + fragColor = vertexColor; + } +)"; + + + + + +void EaselVertex::init_shaders() { + unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); + glCompileShader(vertexShader); + // check for shader compile errors + int success; + char infoLog[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; + } + // fragment shader + unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); + glCompileShader(fragmentShader); + // check for shader compile errors + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; + } + // link shaders + shaderProgram = glCreateProgram(); + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + glLinkProgram(shaderProgram); + // check for linking errors + glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); + if (!success) { + glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; + } + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + +} + + +void EaselVertex::create_vertex_buffer() { + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + // Create and bind the vertex buffer object (VBO) + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + + + glBufferData(GL_ARRAY_BUFFER, vertex_buffer_maximum()*3*sizeof(float), 0, GL_STATIC_DRAW); + // Specify the vertex attribute pointers + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); +} + +void EaselVertex::destroy_vertex_buffer() { + glDeleteVertexArrays(1, &vao); + glDeleteBuffers(1, &vbo); +} + +EaselVertex::EaselVertex() +{ + init_shaders(); + create_vertex_buffer(); +} + + +EaselVertex::~EaselVertex() { + destroy_vertex_buffer(); + glDeleteProgram(shaderProgram); +} + + +void EaselVertex::render() { + glUseProgram(shaderProgram); + int vertexColorLocation = glGetUniformLocation(shaderProgram, "vertexColor"); + glUniform4f(vertexColorLocation, vertex_color.x, vertex_color.y, vertex_color.z, vertex_color.w); + + + unsigned maxv = vertex_buffer_maximum(); + if (m_vertices.size() > 0) { + unsigned offset = total_vertices; + if (offset > maxv) { + offset = total_vertices%maxv; + } + unsigned offset_n = offset - m_vertices.size()/3; + unsigned offset_b = offset_n*3*sizeof(float); + //printf("[%d %d]", offset, m_vertices.size()/3); + //printf("%.2f_%.2f ", m_vertices.at(0), m_vertices.at(1)); + //fflush(stdout); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferSubData(GL_ARRAY_BUFFER, offset_b, m_vertices.size()*sizeof(float), m_vertices.data()); + } + + glBindVertexArray(vao); + auto to_draw = total_vertices>maxv ? maxv : total_vertices; + glDrawArrays(GL_POINTS, 0, to_draw); + glBindVertexArray(0); + + m_vertices.clear(); +} + +void EaselVertex::gui() { + ImGui::ColorEdit4("Vertex color", (float*)&vertex_color); + if (ScrollableSliderUInt("Max vertex", &vertex_buffer_maximum_k, 1024, 1024*32, "%d", 32)) { + destroy_vertex_buffer(); + create_vertex_buffer(); + } + ScrollableSliderUInt("Frame vertex target", &frame_vertex_target_k, 1, vertex_buffer_maximum_k, "%d", 8); +} + +void EaselVertex::dab(float x, float y) { + m_vertices.push_back(x); + m_vertices.push_back(y); + m_vertices.push_back(0); + ++total_vertices; + // TODO: handle total_vertices overflow +} + +/* +void EaselVertex::dab(uint32_t x, uint32_t y, uint32_t c) { + dab((float)x, (float)y); +} +*/ + +void EaselVertex::drawdot(int32_t x, int32_t y, uint32_t c) { + dab((float)x/w-0.5, (float)y/h-0.5); +} + +void EaselVertex::clear() { + total_vertices = 0; +} + +/* +unsigned EaselVertex::vertex_buffer_maximum() const { + return vertex_buffer_maximum_k * 1024; +} +*/ diff --git a/easelvertex.h b/easelvertex.h new file mode 100644 index 0000000..0f2703e --- /dev/null +++ b/easelvertex.h @@ -0,0 +1,26 @@ +#pragma once +#include "easel.h" + +class EaselVertex : public Easel { +public: + EaselVertex(); + ~EaselVertex(); + + void dab(float x, float y); + void drawdot(int32_t x, int32_t y, uint32_t c) override; + + virtual void render() override; + virtual void clear() override; + virtual void gui() override; + +private: + void init_shaders(); + void create_vertex_buffer(); + void destroy_vertex_buffer(); + unsigned total_vertices = 0; + unsigned vao, vbo; + std::vector m_vertices; + GLuint shaderProgram; + ImVec4 vertex_color = ImVec4(1, 0.5, 0.2, 0.1f); + +}; diff --git a/main.cpp b/main.cpp index 0fb6d8c..76d48e2 100644 --- a/main.cpp +++ b/main.cpp @@ -22,27 +22,6 @@ #include "artfactory.h" - -const char* vertexShaderSource = R"( - #version 330 core - layout (location = 0) in vec3 aPos; - void main() - { - gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); - } -)"; - -const char* fragmentShaderSource = R"( - #version 330 core - out vec4 fragColor; - uniform vec4 vertexColor; - void main() - { - fragColor = vertexColor; - } -)"; - - std::unique_ptr art; static GLFWwindow* window; @@ -57,98 +36,6 @@ bool get_window_size() { return resized; } -typedef uint32_t pixel_t; -pixel_t *image_data = NULL; -std::vector image_data_vector; -#define texture_size (art->tex_w * art->tex_h * sizeof(pixel_t)) - -GLuint image_texture; -GLuint pboIds[2]; -int pbo_index = 0; - -GLuint shaderProgram; - -// GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT, GL_REPEAT, GL_MIRROR_CLAMP_TO_EDGE - -void init_shaders() { - unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); - glCompileShader(vertexShader); - // check for shader compile errors - int success; - char infoLog[512]; - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); - if (!success) - { - glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; - } - // fragment shader - unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); - glCompileShader(fragmentShader); - // check for shader compile errors - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); - if (!success) - { - glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; - } - // link shaders - shaderProgram = glCreateProgram(); - glAttachShader(shaderProgram, vertexShader); - glAttachShader(shaderProgram, fragmentShader); - glLinkProgram(shaderProgram); - // check for linking errors - glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); - if (!success) { - glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; - } - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - -} - -void make_pbos() { - return; - image_data_vector.resize(texture_size); - image_data = image_data_vector.data(); - - // AUTHOR: Song Ho Ahn (song.ahn@gmail.com) - // http://www.songho.ca/opengl/gl_pbo.html - glGenTextures(1, &image_texture); - glBindTexture(GL_TEXTURE_2D, image_texture); - 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_REPEAT); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, - 0, GL_RGBA, art->tex_w, art->tex_h, - 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image_data); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenBuffers(2, pboIds); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[0]); - glBufferData(GL_PIXEL_UNPACK_BUFFER, texture_size, - 0, GL_STREAM_DRAW); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[1]); - glBufferData(GL_PIXEL_UNPACK_BUFFER, texture_size, - 0, GL_STREAM_DRAW); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); -} - -void destroy_pbos() { - return; - glDeleteTextures(1, &image_texture); - glDeleteBuffers(2, pboIds); -} - - static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "Glfw Error %d: %s\n", error, description); @@ -226,13 +113,12 @@ int main(int argc, char *argv[]) ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version); - init_shaders(); + //init_shaders(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable( GL_BLEND ); ImVec4 clear_color = ImVec4(0, 0, 0, 1.00f); - ImVec4 vertex_color = ImVec4(1, 0.5, 0.2, 1.00f); ArtFactory af; if (artarg != -1) @@ -241,7 +127,7 @@ int main(int argc, char *argv[]) get_window_size(); art->resized(sw, sh); - make_pbos(); + //make_pbos(); while (!glfwWindowShouldClose(window)) { @@ -262,17 +148,15 @@ int main(int argc, char *argv[]) { art = af.get_art(); art->resized(sw, sh); - destroy_pbos(); - make_pbos(); + //destroy_pbos(); + //make_pbos(); } if (ImGui::CollapsingHeader("Clear Configuration")) { - ScrollableSliderUInt("force clear every N frames", &art->clear_every, 0, 1024, "%d", 1); ScrollableSliderUInt("Max 1k frames before reinit", &art->max_kframes, 0, 1024, "%d", 1); ImGui::ColorEdit4("Clear color", (float*)&clear_color); - ImGui::ColorEdit4("Vertex color", (float*)&vertex_color); } bool resize_pbo = art->gui(); @@ -294,41 +178,16 @@ int main(int argc, char *argv[]) resize_pbo |= art->frame_number > art->max_kframes*1024; if (get_window_size() || resize_pbo) { art->resized(sw, sh); - destroy_pbos(); - make_pbos(); + //destroy_pbos(); + //make_pbos(); } - glUseProgram(shaderProgram); - int vertexColorLocation = glGetUniformLocation(shaderProgram, "vertexColor"); - glUniform4f(vertexColorLocation, vertex_color.x, vertex_color.y, vertex_color.z, vertex_color.w); art->draw(0); -#if 0 - int nexti = pbo_index; - pbo_index = pbo_index ? 0 : 1; - glBindTexture(GL_TEXTURE_2D, image_texture); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[pbo_index]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - art->tex_w, art->tex_h, GL_RGBA, GL_UNSIGNED_BYTE, 0); - //glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - - - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIds[nexti]); - glBufferData(GL_PIXEL_UNPACK_BUFFER, texture_size, - 0, GL_STREAM_DRAW); - uint32_t* ptr = (uint32_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); - assert(ptr); - art->draw(ptr); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - - ImGui::GetBackgroundDrawList()->AddImage((void*)(intptr_t)image_texture, - ImVec2(0, 0), ImVec2(sw, sh), - ImVec2(0, 0), ImVec2((float)sw/art->tex_w, (float)sh/art->tex_h)); -#endif ImGui::Render(); glViewport(0, 0, sw, sh); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); @@ -342,9 +201,6 @@ int main(int argc, char *argv[]) ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); - destroy_pbos(); - -glDeleteProgram(shaderProgram); glfwDestroyWindow(window); glfwTerminate(); diff --git a/mtron.cpp b/mtron.cpp index 21059cf..4bbc1ef 100644 --- a/mtron.cpp +++ b/mtron.cpp @@ -12,6 +12,7 @@ void Minskytron::resize(int _w, int _h) { tex_w = tex_h = 1 << tex_power; + easel->set_texture_size(tex_w, tex_h); ya=0; xa=0737777<set_texture_size(tex_w, tex_h); npix = (width + 2) * (height + 2); r1.resize(npix); r2.resize(npix); diff --git a/thornbird.h b/thornbird.h index eceeacf..737272d 100644 --- a/thornbird.h +++ b/thornbird.h @@ -34,9 +34,6 @@ class Thornbird : public Art { public: Thornbird() : Art("thornbird --- continuously varying Thornbird set") { - //pb = std::make_unique(); - use_pixel_buffer = true; - pixel_buffer_maximum = 1024*512; } private: virtual bool render_gui() override;