From 1402da63025fa0026d2a4a6d73535a8f4f2e4814 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini Date: Thu, 27 Aug 2020 14:59:29 +0200 Subject: [PATCH] More OpenGL cleanup (#1056) --- apps/ysceneview/ysceneview.cpp | 25 ++- apps/ysceneviews/ysceneviews.cpp | 22 +- apps/yshapeview/yshapeview.cpp | 41 ++-- libs/yocto_gui/yocto_draw.cpp | 292 +++++++++++++------------- libs/yocto_gui/yocto_draw.h | 337 ++++++++++++++++--------------- libs/yocto_gui/yocto_opengl.cpp | 51 ++--- libs/yocto_gui/yocto_opengl.h | 35 ++-- 7 files changed, 406 insertions(+), 397 deletions(-) diff --git a/apps/ysceneview/ysceneview.cpp b/apps/ysceneview/ysceneview.cpp index 2c53b8599..d554dcafa 100644 --- a/apps/ysceneview/ysceneview.cpp +++ b/apps/ysceneview/ysceneview.cpp @@ -56,15 +56,15 @@ struct app_state { string name = ""; // options - gui_scene_params drawgl_prms = {}; + shade_params drawgl_prms = {}; // scene sceneio_scene* ioscene = new sceneio_scene{}; sceneio_camera* iocamera = nullptr; // rendering state - gui_scene* glscene = new gui_scene{}; - gui_camera* glcamera = nullptr; + shade_scene* glscene = new shade_scene{}; + shade_camera* glcamera = nullptr; // editing sceneio_camera* selected_camera = nullptr; @@ -97,7 +97,7 @@ struct app_states { std::deque loading = {}; // default options - gui_scene_params drawgl_prms = {}; + shade_params drawgl_prms = {}; // cleanup ~app_states() { @@ -129,8 +129,8 @@ void load_scene_async( if (!apps->selected) apps->selected = app; } -void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, - gui_camera*& glcamera, sceneio_camera* iocamera, +void init_glscene(shade_scene* glscene, sceneio_scene* ioscene, + shade_camera*& glcamera, sceneio_camera* iocamera, progress_callback progress_cb) { // handle progress auto progress = vec2i{ @@ -142,7 +142,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, init_scene(glscene); // camera - auto camera_map = unordered_map{}; + auto camera_map = unordered_map{}; camera_map[nullptr] = nullptr; for (auto iocamera : ioscene->cameras) { if (progress_cb) progress_cb("convert camera", progress.x++, progress.y); @@ -154,7 +154,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, } // textures - auto texture_map = unordered_map{}; + auto texture_map = unordered_map{}; texture_map[nullptr] = nullptr; for (auto iotexture : ioscene->textures) { if (progress_cb) progress_cb("convert texture", progress.x++, progress.y); @@ -168,7 +168,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, } // material - auto material_map = unordered_map{}; + auto material_map = unordered_map{}; material_map[nullptr] = nullptr; for (auto iomaterial : ioscene->materials) { if (progress_cb) progress_cb("convert material", progress.x++, progress.y); @@ -192,7 +192,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, } // shapes - auto shape_map = unordered_map{}; + auto shape_map = unordered_map{}; shape_map[nullptr] = nullptr; for (auto ioshape : ioscene->shapes) { if (progress_cb) progress_cb("convert shape", progress.x++, progress.y); @@ -425,11 +425,10 @@ void draw_widgets(gui_window* win, app_states* apps, const gui_input& input) { } auto& params = app->drawgl_prms; draw_slider(win, "resolution", params.resolution, 0, 4096); - draw_combobox(win, "lighting", (int&)params.lighting, gui_lighting_names); + draw_combobox(win, "lighting", (int&)params.lighting, shade_lighting_names); draw_checkbox(win, "wireframe", params.wireframe); continue_line(win); draw_checkbox(win, "faceted", params.faceted); - // draw_checkbox(win, "edges", params.edges); continue_line(win); draw_checkbox(win, "double sided", params.double_sided); draw_slider(win, "exposure", params.exposure, -10, 10); @@ -604,7 +603,7 @@ int main(int argc, const char* argv[]) { add_option(cli, "--resolution,-r", apps->drawgl_prms.resolution, "Image resolution."); add_option(cli, "--lighting", apps->drawgl_prms.lighting, "Lighting type.", - gui_lighting_names); + shade_lighting_names); add_option(cli, "scenes", filenames, "Scene filenames", true); parse_cli(cli, argc, argv); diff --git a/apps/ysceneviews/ysceneviews.cpp b/apps/ysceneviews/ysceneviews.cpp index 64dfea603..930bca54e 100644 --- a/apps/ysceneviews/ysceneviews.cpp +++ b/apps/ysceneviews/ysceneviews.cpp @@ -57,15 +57,15 @@ struct app_state { string name = ""; // options - gui_scene_params drawgl_prms = {}; + shade_params drawgl_prms = {}; // scene sceneio_scene* ioscene = new sceneio_scene{}; sceneio_camera* iocamera = nullptr; // rendering state - gui_scene* glscene = new gui_scene{}; - gui_camera* glcamera = nullptr; + shade_scene* glscene = new shade_scene{}; + shade_camera* glcamera = nullptr; // editing sceneio_camera* selected_camera = nullptr; @@ -90,8 +90,8 @@ struct app_state { } }; -void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, - gui_camera*& glcamera, sceneio_camera* iocamera, +void init_glscene(shade_scene* glscene, sceneio_scene* ioscene, + shade_camera*& glcamera, sceneio_camera* iocamera, progress_callback progress_cb) { // handle progress auto progress = vec2i{ @@ -103,7 +103,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, init_scene(glscene); // camera - auto camera_map = unordered_map{}; + auto camera_map = unordered_map{}; camera_map[nullptr] = nullptr; for (auto iocamera : ioscene->cameras) { if (progress_cb) progress_cb("convert camera", progress.x++, progress.y); @@ -115,7 +115,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, } // textures - auto texture_map = unordered_map{}; + auto texture_map = unordered_map{}; texture_map[nullptr] = nullptr; for (auto iotexture : ioscene->textures) { if (progress_cb) progress_cb("convert texture", progress.x++, progress.y); @@ -129,7 +129,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, } // material - auto material_map = unordered_map{}; + auto material_map = unordered_map{}; material_map[nullptr] = nullptr; for (auto iomaterial : ioscene->materials) { if (progress_cb) progress_cb("convert material", progress.x++, progress.y); @@ -153,7 +153,7 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene, } // shapes - auto shape_map = unordered_map{}; + auto shape_map = unordered_map{}; shape_map[nullptr] = nullptr; for (auto ioshape : ioscene->shapes) { if (progress_cb) progress_cb("convert shape", progress.x++, progress.y); @@ -202,7 +202,7 @@ int main(int argc, const char* argv[]) { add_option( cli, "--resolution,-r", app->drawgl_prms.resolution, "Image resolution."); add_option(cli, "--lighting", app->drawgl_prms.lighting, "Lighting type.", - gui_lighting_names); + shade_lighting_names); add_option(cli, "scene", app->filename, "Scene filename", true); parse_cli(cli, argc, argv); @@ -249,7 +249,7 @@ int main(int argc, const char* argv[]) { draw_checkbox(win, "faceted", params.faceted); continue_line(win); draw_checkbox(win, "double sided", params.double_sided); - draw_combobox(win, "lighting", (int&)params.lighting, gui_lighting_names); + draw_combobox(win, "lighting", (int&)params.lighting, shade_lighting_names); // draw_checkbox(win, "edges", params.edges); draw_slider(win, "exposure", params.exposure, -10, 10); draw_slider(win, "gamma", params.gamma, 0.1f, 4); diff --git a/apps/yshapeview/yshapeview.cpp b/apps/yshapeview/yshapeview.cpp index a3b7752ee..14c99b529 100644 --- a/apps/yshapeview/yshapeview.cpp +++ b/apps/yshapeview/yshapeview.cpp @@ -56,14 +56,14 @@ struct app_state { string name = ""; // options - gui_scene_params drawgl_prms = {}; + shade_params drawgl_prms = {}; // scene generic_shape* ioshape = new generic_shape{}; // rendering state - gui_scene* glscene = new gui_scene{}; - gui_camera* glcamera = nullptr; + shade_scene* glscene = new shade_scene{}; + shade_camera* glcamera = nullptr; // loading status std::atomic ok = false; @@ -88,7 +88,7 @@ struct app_states { std::deque loading = {}; // default options - gui_scene_params drawgl_prms = {}; + shade_params drawgl_prms = {}; // cleanup ~app_states() { @@ -169,7 +169,7 @@ quads_shape make_cylinders(const vector& lines, const char* draw_instanced_vertex_code(); -void init_glscene(app_state* app, gui_scene* glscene, generic_shape* ioshape, +void init_glscene(app_state* app, shade_scene* glscene, generic_shape* ioshape, progress_callback progress_cb) { // handle progress auto progress = vec2i{0, 4}; @@ -195,6 +195,8 @@ void init_glscene(app_state* app, gui_scene* glscene, generic_shape* ioshape, auto glmaterial = add_material(glscene, {0, 0, 0}, {0.5, 1, 0.5}, 1, 0, 0.2); auto glmateriale = add_material(glscene, {0, 0, 0}, {0, 0, 0}, 0, 0, 1); auto glmaterialv = add_material(glscene, {0, 0, 0}, {0, 0, 0}, 0, 0, 1); + set_unlit(glmateriale, true); + set_unlit(glmaterialv, true); // shapes if (progress_cb) progress_cb("convert shape", progress.x++, progress.y); @@ -240,33 +242,16 @@ void init_glscene(app_state* app, gui_scene* glscene, generic_shape* ioshape, // shapes if (progress_cb) progress_cb("convert instance", progress.x++, progress.y); - add_instance(glscene, identity3x4f, model_shape, glmaterial); - - auto edges_instance = add_instance( - glscene, identity3x4f, edges_shape, glmateriale, true); - edges_instance->shading = gui_shading_type::constant; - - auto points_instance = add_instance( - glscene, identity3x4f, vertices_shape, glmaterialv, true); - points_instance->shading = gui_shading_type::constant; + add_instance(glscene, identity3x4f, edges_shape, glmateriale, true); + add_instance(glscene, identity3x4f, vertices_shape, glmaterialv, true); // override eyelight vertex shader - auto vert = draw_instanced_vertex_code(); - auto frag = draw_instances_eyelight_fragment_code(); - init_program(glscene->camlight_program, vert, frag); + set_program(glscene->camlight_program, draw_instanced_vertex_code(), + draw_instances_eyelight_fragment_code()); // done if (progress_cb) progress_cb("convert done", progress.x++, progress.y); - - // init_program(glscene->ibl_program, vertex_source, - // draw_instances_ibl_fragment_code(), error, errorb); - - // auto img = image{}; - // load_image("apps/yshapeview/env.hdr", img, error); - // auto texture = new ogl_texture{}; - // set_texture(texture, img, true, true, true); - // init_ibl_data(glscene, texture, {1, 1, 1}); } // draw with shading @@ -319,7 +304,7 @@ void draw_widgets(gui_window* win, app_states* apps, const gui_input& input) { draw_checkbox(win, "points", app->glscene->instances[2]->hidden, true); draw_coloredit(win, "color", glmaterial->color); draw_slider(win, "resolution", params.resolution, 0, 4096); - draw_combobox(win, "lighting", (int&)params.lighting, gui_lighting_names); + draw_combobox(win, "lighting", (int&)params.lighting, shade_lighting_names); draw_checkbox(win, "wireframe", params.wireframe); continue_line(win); draw_checkbox(win, "double sided", params.double_sided); @@ -401,7 +386,7 @@ int main(int argc, const char* argv[]) { add_option(cli, "--resolution,-r", apps->drawgl_prms.resolution, "Image resolution."); add_option(cli, "--lighting", apps->drawgl_prms.lighting, "Lighting type.", - gui_lighting_names); + shade_lighting_names); add_option(cli, "shapes", filenames, "Shape filenames", true); parse_cli(cli, argc, argv); diff --git a/libs/yocto_gui/yocto_draw.cpp b/libs/yocto_gui/yocto_draw.cpp index e82084494..860148b1b 100644 --- a/libs/yocto_gui/yocto_draw.cpp +++ b/libs/yocto_gui/yocto_draw.cpp @@ -55,63 +55,63 @@ namespace yocto { #pragma GCC diagnostic pop #endif -ogl_arraybuffer* get_positions(gui_shape* shape) { +const ogl_arraybuffer* get_positions(const shade_shape* shape) { if (shape->shape->vertex_buffers.size() <= 0) return nullptr; return shape->shape->vertex_buffers[0]; } -ogl_arraybuffer* get_normals(gui_shape* shape) { +const ogl_arraybuffer* get_normals(const shade_shape* shape) { if (shape->shape->vertex_buffers.size() <= 1) return nullptr; return shape->shape->vertex_buffers[1]; } -ogl_arraybuffer* get_texcoords(gui_shape* shape) { +const ogl_arraybuffer* get_texcoords(const shade_shape* shape) { if (shape->shape->vertex_buffers.size() <= 2) return nullptr; return shape->shape->vertex_buffers[2]; } -ogl_arraybuffer* get_colors(gui_shape* shape) { +const ogl_arraybuffer* get_colors(const shade_shape* shape) { if (shape->shape->vertex_buffers.size() <= 3) return nullptr; return shape->shape->vertex_buffers[3]; } -ogl_arraybuffer* get_tangents(gui_shape* shape) { +const ogl_arraybuffer* get_tangents(const shade_shape* shape) { if (shape->shape->vertex_buffers.size() <= 4) return nullptr; return shape->shape->vertex_buffers[4]; } -void set_positions(gui_shape* shape, const vector& positions) { +void set_positions(shade_shape* shape, const vector& positions) { if (positions.empty()) { set_vertex_buffer(shape->shape, vec3f{0, 0, 0}, 0); } else { set_vertex_buffer(shape->shape, positions, 0); } } -void set_normals(gui_shape* shape, const vector& normals) { +void set_normals(shade_shape* shape, const vector& normals) { if (normals.empty()) { set_vertex_buffer(shape->shape, vec3f{0, 0, 1}, 1); } else { set_vertex_buffer(shape->shape, normals, 1); } } -void set_texcoords(gui_shape* shape, const vector& texcoords) { +void set_texcoords(shade_shape* shape, const vector& texcoords) { if (texcoords.empty()) { set_vertex_buffer(shape->shape, vec2f{0, 0}, 2); } else { set_vertex_buffer(shape->shape, texcoords, 2); } } -void set_colors(gui_shape* shape, const vector& colors) { +void set_colors(shade_shape* shape, const vector& colors) { if (colors.empty()) { set_vertex_buffer(shape->shape, vec4f{1, 1, 1, 1}, 3); } else { set_vertex_buffer(shape->shape, colors, 3); } } -void set_tangents(gui_shape* shape, const vector& tangents) { +void set_tangents(shade_shape* shape, const vector& tangents) { if (tangents.empty()) { set_vertex_buffer(shape->shape, vec4f{0, 0, 1, 1}, 4); } else { set_vertex_buffer(shape->shape, tangents, 4); } } -void set_instance_from(gui_shape* shape, const vector& froms) { +void set_instance_from(shade_shape* shape, const vector& froms) { if (froms.empty()) { set_vertex_buffer(shape->shape, vec3f{0, 0, 0}, 5); set_instance_buffer(shape->shape, 5, false); @@ -120,7 +120,7 @@ void set_instance_from(gui_shape* shape, const vector& froms) { set_instance_buffer(shape->shape, 5, true); } } -void set_instance_to(gui_shape* shape, const vector& tos) { +void set_instance_to(shade_shape* shape, const vector& tos) { if (tos.empty()) { set_vertex_buffer(shape->shape, vec3f{0, 0, 0}, 5); set_instance_buffer(shape->shape, 6, false); @@ -130,16 +130,16 @@ void set_instance_to(gui_shape* shape, const vector& tos) { } } -void set_points(gui_shape* shape, const vector& points) { +void set_points(shade_shape* shape, const vector& points) { set_index_buffer(shape->shape, points); } -void set_lines(gui_shape* shape, const vector& lines) { +void set_lines(shade_shape* shape, const vector& lines) { set_index_buffer(shape->shape, lines); } -void set_triangles(gui_shape* shape, const vector& triangles) { +void set_triangles(shade_shape* shape, const vector& triangles) { set_index_buffer(shape->shape, triangles); } -void set_quads(gui_shape* shape, const vector& quads) { +void set_quads(shade_shape* shape, const vector& quads) { auto triangles = vector{}; triangles.reserve(quads.size() * 2); for (auto& q : quads) { @@ -149,7 +149,7 @@ void set_quads(gui_shape* shape, const vector& quads) { set_index_buffer(shape->shape, triangles); } -gui_scene::~gui_scene() { +shade_scene::~shade_scene() { clear_scene(this); for (auto camera : cameras) delete camera; for (auto shape : shapes) delete shape; @@ -170,35 +170,41 @@ static const char* precompute_environment_fragment_code(); static const char* precompute_irradiance_fragment_code(); static const char* precompute_reflections_fragment_code(); -static void init_environment(gui_environment* environment); -static void init_envlight(gui_environment* environment); +static void init_environment(shade_environment* environment); +static void init_envlight(shade_environment* environment); // Initialize an OpenGL scene -void init_scene(gui_scene* scene) { +void init_scene(shade_scene* scene) { if (is_initialized(scene->camlight_program)) return; auto error = ""s, errorlog = ""s; - init_program(scene->camlight_program, draw_instances_vertex_code(), + set_program(scene->camlight_program, draw_instances_vertex_code(), draw_instances_eyelight_fragment_code(), error, errorlog); - init_program(scene->envlight_program, draw_instances_vertex_code(), + set_program(scene->envlight_program, draw_instances_vertex_code(), draw_instances_ibl_fragment_code(), error, errorlog); - init_program(scene->environment_program, precompute_cubemap_vertex_code(), + set_program(scene->environment_program, precompute_cubemap_vertex_code(), draw_enivronment_fragment_code()); } -bool is_initialized(gui_scene* scene) { +bool is_initialized(shade_scene* scene) { return scene && is_initialized(scene->camlight_program); } // Initialize data for environment lighting -void init_environments(gui_scene* scene, bool precompute_envlight) { +void init_environments(shade_scene* scene, bool precompute_envlight) { for (auto environment : scene->environments) { init_environment(environment); if (precompute_envlight) init_envlight(environment); } } +// Check if we have an envlight +bool has_envlight(const shade_scene* scene) { + return !scene->environments.empty() && + is_initialized(scene->environments.front()->cubemap); +} + // Clear an OpenGL scene -void clear_scene(gui_scene* scene) { +void clear_scene(shade_scene* scene) { for (auto texture : scene->textures) clear_texture(texture); for (auto shape : scene->shapes) clear_shape(shape); for (auto environment : scene->environments) clear_environment(environment); @@ -208,8 +214,8 @@ void clear_scene(gui_scene* scene) { } // Initialize an OpenGL scene -[[deprecated]] void init_scene(gui_scene* scene, gui_texture* environment_tex, - const vec3f& environment_emission) { +[[deprecated]] void init_scene(shade_scene* scene, + shade_texture* environment_tex, const vec3f& environment_emission) { if (is_initialized(scene->camlight_program)) return; if (environment_tex && environment_emission != vec3f{0, 0, 0}) { add_environment(scene, identity3x4f, environment_emission, environment_tex); @@ -219,139 +225,140 @@ void clear_scene(gui_scene* scene) { } // add camera -gui_camera* add_camera(gui_scene* scene) { - return scene->cameras.emplace_back(new gui_camera{}); +shade_camera* add_camera(shade_scene* scene) { + return scene->cameras.emplace_back(new shade_camera{}); } -void set_frame(gui_camera* camera, const frame3f& frame) { +void set_frame(shade_camera* camera, const frame3f& frame) { camera->frame = frame; } -void set_lens(gui_camera* camera, float lens, float aspect, float film) { +void set_lens(shade_camera* camera, float lens, float aspect, float film) { camera->lens = lens; camera->aspect = aspect; camera->film = film; } -void set_nearfar(gui_camera* camera, float near, float far) { +void set_nearfar(shade_camera* camera, float near, float far) { camera->near = near; camera->far = far; } // add texture -gui_texture* add_texture(gui_scene* scene) { - return scene->textures.emplace_back(new gui_texture{}); +shade_texture* add_texture(shade_scene* scene) { + return scene->textures.emplace_back(new shade_texture{}); } // cleanup -gui_texture::~gui_texture() { delete texture; } +shade_texture::~shade_texture() { delete texture; } // check if initialized -bool is_initialized(const gui_texture* texture) { +bool is_initialized(const shade_texture* texture) { return is_initialized(texture->texture); } // clear texture -void clear_texture(gui_texture* texture) { clear_texture(texture->texture); } +void clear_texture(shade_texture* texture) { clear_texture(texture->texture); } // set texture -void set_texture(gui_texture* texture, const image& img, bool as_srgb, +void set_texture(shade_texture* texture, const image& img, bool as_srgb, bool linear, bool mipmap) { set_texture(texture->texture, img, as_srgb, linear, mipmap); } -void set_texture(gui_texture* texture, const image& img, bool as_float, +void set_texture(shade_texture* texture, const image& img, bool as_float, bool linear, bool mipmap) { set_texture(texture->texture, img, as_float, linear, mipmap); } -void set_texture(gui_texture* texture, const image& img, bool as_srgb, +void set_texture(shade_texture* texture, const image& img, bool as_srgb, bool linear, bool mipmap) { set_texture(texture->texture, img, as_srgb, linear, mipmap); } -void set_texture(gui_texture* texture, const image& img, bool as_float, +void set_texture(shade_texture* texture, const image& img, bool as_float, bool linear, bool mipmap) { set_texture(texture->texture, img, as_float, linear, mipmap); } -void set_texture(gui_texture* texture, const image& img, bool as_srgb, +void set_texture(shade_texture* texture, const image& img, bool as_srgb, bool linear, bool mipmap) { set_texture(texture->texture, img, as_srgb, linear, mipmap); } -void set_texture(gui_texture* texture, const image& img, bool as_float, +void set_texture(shade_texture* texture, const image& img, bool as_float, bool linear, bool mipmap) { set_texture(texture->texture, img, as_float, linear, mipmap); } // cleanup -gui_shape::~gui_shape() { delete shape; } +shade_shape::~shade_shape() { delete shape; } // cheeck if initialized -bool is_initialized(const gui_shape* shape) { +bool is_initialized(const shade_shape* shape) { return is_initialized(shape->shape); } // clear -void clear_shape(gui_shape* shape) { clear_shape(shape->shape); } +void clear_shape(shade_shape* shape) { clear_shape(shape->shape); } // add shape -gui_shape* add_shape(gui_scene* scene) { - auto shape = scene->shapes.emplace_back(new gui_shape{}); - init_shape(shape->shape); - return shape; +shade_shape* add_shape(shade_scene* scene) { + return scene->shapes.emplace_back(new shade_shape{}); } // add instance -gui_instance* add_instance(gui_scene* scene) { - return scene->instances.emplace_back(new gui_instance{}); +shade_instance* add_instance(shade_scene* scene) { + return scene->instances.emplace_back(new shade_instance{}); } -void set_frame(gui_instance* instance, const frame3f& frame) { +void set_frame(shade_instance* instance, const frame3f& frame) { instance->frame = frame; } -void set_shape(gui_instance* instance, gui_shape* shape) { +void set_shape(shade_instance* instance, shade_shape* shape) { instance->shape = shape; } -void set_material(gui_instance* instance, gui_material* material) { +void set_material(shade_instance* instance, shade_material* material) { instance->material = material; } -void set_hidden(gui_instance* instance, bool hidden) { +void set_hidden(shade_instance* instance, bool hidden) { instance->hidden = hidden; } -void set_highlighted(gui_instance* instance, bool highlighted) { +void set_highlighted(shade_instance* instance, bool highlighted) { instance->highlighted = highlighted; } // add material -gui_material* add_material(gui_scene* scene) { - return scene->materials.emplace_back(new gui_material{}); +shade_material* add_material(shade_scene* scene) { + return scene->materials.emplace_back(new shade_material{}); } -void set_emission( - gui_material* material, const vec3f& emission, gui_texture* emission_tex) { +void set_emission(shade_material* material, const vec3f& emission, + shade_texture* emission_tex) { material->emission = emission; material->emission_tex = emission_tex; } void set_color( - gui_material* material, const vec3f& color, gui_texture* color_tex) { + shade_material* material, const vec3f& color, shade_texture* color_tex) { material->color = color; material->color_tex = color_tex; } void set_specular( - gui_material* material, float specular, gui_texture* specular_tex) { + shade_material* material, float specular, shade_texture* specular_tex) { material->specular = specular; material->specular_tex = specular_tex; } void set_roughness( - gui_material* material, float roughness, gui_texture* roughness_tex) { + shade_material* material, float roughness, shade_texture* roughness_tex) { material->roughness = roughness; material->roughness_tex = roughness_tex; } void set_opacity( - gui_material* material, float opacity, gui_texture* opacity_tex) { + shade_material* material, float opacity, shade_texture* opacity_tex) { material->opacity = opacity; } void set_metallic( - gui_material* material, float metallic, gui_texture* metallic_tex) { + shade_material* material, float metallic, shade_texture* metallic_tex) { material->metallic = metallic; material->metallic_tex = metallic_tex; } -void set_normalmap(gui_material* material, gui_texture* normal_tex) { +void set_normalmap(shade_material* material, shade_texture* normal_tex) { material->normal_tex = normal_tex; } +void set_unlit(shade_material* material, bool unlit) { + material->unlit = unlit; +} -gui_shape* add_shape(gui_scene* scene, const vector& points, +shade_shape* add_shape(shade_scene* scene, const vector& points, const vector& lines, const vector& triangles, const vector& quads, const vector& positions, const vector& normals, const vector& texcoords, @@ -374,7 +381,7 @@ gui_shape* add_shape(gui_scene* scene, const vector& points, } // cleanup -gui_environment::~gui_environment() { +shade_environment::~shade_environment() { delete shape; delete cubemap; delete envlight_diffuse; @@ -383,12 +390,12 @@ gui_environment::~gui_environment() { } // cheeck if initialized -bool is_initialized(const gui_environment* environment) { +bool is_initialized(const shade_environment* environment) { return is_initialized(environment->shape); } // clear -void clear_environment(gui_environment* environment) { +void clear_environment(shade_environment* environment) { clear_shape(environment->shape); clear_cubemap(environment->cubemap); clear_cubemap(environment->envlight_diffuse); @@ -397,20 +404,20 @@ void clear_environment(gui_environment* environment) { } // environment properties -gui_environment* add_environment(gui_scene* scene) { - return scene->environments.emplace_back(new gui_environment{}); +shade_environment* add_environment(shade_scene* scene) { + return scene->environments.emplace_back(new shade_environment{}); } -void set_frame(gui_environment* environment, const frame3f& frame) { +void set_frame(shade_environment* environment, const frame3f& frame) { environment->frame = frame; } -void set_emission(gui_environment* environment, const vec3f& emission, - gui_texture* emission_tex) { +void set_emission(shade_environment* environment, const vec3f& emission, + shade_texture* emission_tex) { environment->emission = emission; environment->emission_tex = emission_tex; } // shortcuts -gui_camera* add_camera(gui_scene* scene, const frame3f& frame, float lens, +shade_camera* add_camera(shade_scene* scene, const frame3f& frame, float lens, float aspect, float film, float near, float far) { auto camera = add_camera(scene); set_frame(camera, frame); @@ -418,11 +425,11 @@ gui_camera* add_camera(gui_scene* scene, const frame3f& frame, float lens, set_nearfar(camera, near, far); return camera; } -gui_material* add_material(gui_scene* scene, const vec3f& emission, +shade_material* add_material(shade_scene* scene, const vec3f& emission, const vec3f& color, float specular, float metallic, float roughness, - gui_texture* emission_tex, gui_texture* color_tex, - gui_texture* specular_tex, gui_texture* metallic_tex, - gui_texture* roughness_tex, gui_texture* normalmap_tex) { + shade_texture* emission_tex, shade_texture* color_tex, + shade_texture* specular_tex, shade_texture* metallic_tex, + shade_texture* roughness_tex, shade_texture* normalmap_tex) { auto material = add_material(scene); set_emission(material, emission, emission_tex); set_color(material, color, color_tex); @@ -433,8 +440,9 @@ gui_material* add_material(gui_scene* scene, const vec3f& emission, return material; } -gui_instance* add_instance(gui_scene* scene, const frame3f& frame, - gui_shape* shape, gui_material* material, bool hidden, bool highlighted) { +shade_instance* add_instance(shade_scene* scene, const frame3f& frame, + shade_shape* shape, shade_material* material, bool hidden, + bool highlighted) { auto instance = add_instance(scene); set_frame(instance, frame); set_shape(instance, shape); @@ -444,34 +452,38 @@ gui_instance* add_instance(gui_scene* scene, const frame3f& frame, return instance; } -gui_environment* add_environment(gui_scene* scene, const frame3f& frame, - const vec3f& emission, gui_texture* emission_tex) { +shade_environment* add_environment(shade_scene* scene, const frame3f& frame, + const vec3f& emission, shade_texture* emission_tex) { auto environment = add_environment(scene); set_frame(environment, frame); set_emission(environment, emission, emission_tex); return environment; } -void set_scene_view_uniforms(ogl_program* program, const gui_scene_view& view) { +void set_view_uniforms(ogl_program* program, const shade_view& view) { set_uniform(program, "eye", view.camera_frame.o); set_uniform(program, "view", view.view_matrix); set_uniform(program, "projection", view.projection_matrix); - set_uniform(program, "exposure", view.params.exposure); - set_uniform(program, "gamma", view.params.gamma); - set_uniform(program, "faceted", view.params.faceted); - set_uniform(program, "double_sided", view.params.double_sided); +} + +void set_params_uniforms(ogl_program* program, const shade_params& params) { + set_uniform(program, "exposure", params.exposure); + set_uniform(program, "gamma", params.gamma); + set_uniform(program, "double_sided", params.double_sided); } // Draw a shape void set_instance_uniforms(ogl_program* program, const frame3f& frame, - const gui_shape* shape, const gui_material* material, - gui_shading_type shading, bool double_sided, bool non_rigid_frames) { + const shade_shape* shape, const shade_material* material, + const shade_params& params) { auto shape_xform = frame_to_mat(frame); auto shape_inv_xform = transpose( - frame_to_mat(inverse(frame, non_rigid_frames))); + frame_to_mat(inverse(frame, params.non_rigid_frames))); set_uniform(program, "frame", shape_xform); set_uniform(program, "frameit", shape_inv_xform); set_uniform(program, "offset", 0.0f); + set_uniform(program, "faceted", + params.faceted || !is_initialized(get_normals(shape))); // if (instance->highlighted) { // set_uniform(program, "highlight", vec4f{1, 1, 0, 1}); // } else { @@ -479,20 +491,20 @@ void set_instance_uniforms(ogl_program* program, const frame3f& frame, // } auto set_texture = [](ogl_program* program, const char* name, - const char* name_on, gui_texture* texture, int unit) { + const char* name_on, shade_texture* texture, + int unit) { set_uniform(program, name, name_on, texture == nullptr ? nullptr : texture->texture, unit); }; - auto mtype = (int)shading; - set_uniform(program, "mtype", mtype); + set_uniform(program, "mtype", material->unlit ? 0 : 1); set_uniform(program, "emission", material->emission); set_uniform(program, "diffuse", material->color); set_uniform(program, "specular", vec3f{material->metallic, material->metallic, material->metallic}); set_uniform(program, "roughness", material->roughness); set_uniform(program, "opacity", material->opacity); - set_uniform(program, "double_sided", double_sided); + set_uniform(program, "double_sided", params.double_sided); set_texture( program, "emission_tex", "emission_tex_on", material->emission_tex, 0); set_texture(program, "diffuse_tex", "diffuse_tex_on", material->color_tex, 1); @@ -518,13 +530,15 @@ void set_instance_uniforms(ogl_program* program, const frame3f& frame, assert_ogl_error(); } -static void draw_shape(gui_shape* shape) { draw_shape(shape->shape); } +static void draw_shape(shade_shape* shape) { draw_shape(shape->shape); } -void draw_environments(gui_scene* scene, const gui_scene_view& view) { +void draw_environments( + shade_scene* scene, const shade_view& view, const shade_params& params) { auto program = scene->environment_program; if (!is_initialized(program)) return; bind_program(program); - set_scene_view_uniforms(program, view); + set_view_uniforms(program, view); + set_params_uniforms(program, params); for (auto environment : scene->environments) { if (!is_initialized(environment->cubemap)) continue; set_uniform(program, "environment", environment->cubemap, 0); @@ -533,7 +547,8 @@ void draw_environments(gui_scene* scene, const gui_scene_view& view) { unbind_program(); } -void set_eyelight_uniforms(ogl_program* program, const gui_scene_view& view) { +void set_camlight_uniforms( + ogl_program* program, const shade_scene* scene, const shade_view& view) { struct gui_light { vec3f position = {0, 0, 0}; vec3f emission = {0, 0, 0}; @@ -570,46 +585,48 @@ void set_eyelight_uniforms(ogl_program* program, const gui_scene_view& view) { assert_ogl_error(); } -void set_ibl_uniforms(ogl_program* program, const gui_scene* scene) { +void set_envlight_uniforms( + ogl_program* program, const shade_scene* scene, const shade_view& view) { + if (!has_envlight(scene)) return; auto environment = scene->environments.front(); set_uniform(program, "irradiance_cubemap", environment->envlight_diffuse, 6); set_uniform(program, "reflection_cubemap", environment->envlight_specular, 7); set_uniform(program, "brdf_lut", environment->envlight_brdflut, 8); } -void draw_instances(gui_scene* scene, const gui_scene_view& view) { - auto program = scene->camlight_program; - if (!scene->environments.empty() && - is_initialized(scene->environments.front()->cubemap) && - view.params.lighting == gui_lighting_type::envlight) { - program = scene->envlight_program; - } - +void draw_instances( + shade_scene* scene, const shade_view& view, const shade_params& params) { + // set program + auto program = + (params.lighting == shade_lighting_type::camlight || !has_envlight(scene)) + ? scene->camlight_program + : scene->envlight_program; bind_program(program); // set scene uniforms - set_scene_view_uniforms(program, view); + set_view_uniforms(program, view); + set_params_uniforms(program, params); // set lighting uniforms - if (view.params.lighting == gui_lighting_type::camlight) { - set_eyelight_uniforms(program, view); + if (params.lighting == shade_lighting_type::camlight || + !has_envlight(scene)) { + set_camlight_uniforms(program, scene, view); } else { - set_ibl_uniforms(program, scene); + set_envlight_uniforms(program, scene, view); } - set_ogl_wireframe(view.params.wireframe); + set_ogl_wireframe(params.wireframe); for (auto instance : scene->instances) { if (instance->hidden) continue; - set_instance_uniforms(program, instance->frame, instance->shape, - instance->material, instance->shading, view.params.double_sided, - view.params.non_rigid_frames); + set_instance_uniforms( + program, instance->frame, instance->shape, instance->material, params); draw_shape(instance->shape); } unbind_program(); } -gui_scene_view make_scene_view( - gui_camera* camera, const vec4i& viewport, const gui_scene_params& params) { +shade_view make_scene_view( + shade_camera* camera, const vec4i& viewport, const shade_params& params) { auto camera_aspect = (float)viewport.z / (float)viewport.w; auto camera_yfov = camera_aspect >= 0 @@ -619,22 +636,21 @@ gui_scene_view make_scene_view( auto projection_matrix = perspective_mat( camera_yfov, camera_aspect, params.near, params.far); - auto view = gui_scene_view{}; + auto view = shade_view{}; view.camera_frame = camera->frame; view.view_matrix = view_matrix; view.projection_matrix = projection_matrix; - view.params = params; return view; } -void draw_scene(gui_scene* scene, gui_camera* camera, const vec4i& viewport, - const gui_scene_params& params) { +void draw_scene(shade_scene* scene, shade_camera* camera, const vec4i& viewport, + const shade_params& params) { clear_ogl_framebuffer(params.background); set_ogl_viewport(viewport); auto view = make_scene_view(camera, viewport, params); - draw_instances(scene, view); - draw_environments(scene, view); + draw_instances(scene, view, params); + draw_environments(scene, view, params); } // image based lighting @@ -646,14 +662,16 @@ inline void precompute_cubemap(ogl_cubemap* cubemap, const Sampler* environment, ogl_program* program, int size, int num_mipmap_levels = 1, const vec3f& emission = {1, 1, 1}) { // init cubemap with no data - set_cubemap(cubemap, size, 3, true, true, true); + set_cubemap(cubemap, size, 3, + array{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, + true, true, true); auto cube_guard = make_unique(); auto cube = cube_guard.get(); set_cube_shape(cube); auto framebuffer_guard = make_unique(); auto framebuffer = framebuffer_guard.get(); - init_framebuffer(framebuffer, {size, size}); + set_framebuffer(framebuffer, {size, size}); auto cameras = array{ lookat_frame({0, 0, 0}, {1, 0, 0}, {0, 1, 0}), @@ -668,7 +686,7 @@ inline void precompute_cubemap(ogl_cubemap* cubemap, const Sampler* environment, bind_program(program); for (int mipmap_level = 0; mipmap_level < num_mipmap_levels; mipmap_level++) { // resize render buffer and viewport - init_framebuffer(framebuffer, {size, size}); + set_framebuffer(framebuffer, {size, size}); set_ogl_viewport(vec2i{size, size}); for (auto i = 0; i < 6; ++i) { @@ -708,13 +726,13 @@ inline void precompute_specular_brdf_texture(ogl_texture* texture) { auto error = ""s, errorlog = ""s; auto vert = precompute_brdf_vertex_code(); auto frag = precompute_brdf_fragment_code(); - init_program(program, vert, frag, error, errorlog); + set_program(program, vert, frag, error, errorlog); set_texture(texture, size, 3, (float*)nullptr, true, true, false, false); auto framebuffer_guard = make_unique(); auto framebuffer = framebuffer_guard.get(); - init_framebuffer(framebuffer, size); + set_framebuffer(framebuffer, size); set_framebuffer_texture(framebuffer, texture, 0); bind_framebuffer(framebuffer); @@ -732,7 +750,7 @@ inline void precompute_specular_brdf_texture(ogl_texture* texture) { clear_shape(screen_quad); } -static void init_environment(gui_environment* environment) { +static void init_environment(shade_environment* environment) { // init program and shape for drawing the environment set_cube_shape(environment->shape->shape); @@ -740,20 +758,20 @@ static void init_environment(gui_environment* environment) { auto size = environment->emission_tex->texture->size.y; auto program_guard = make_unique(); auto program = program_guard.get(); - init_program(program, precompute_cubemap_vertex_code(), + set_program(program, precompute_cubemap_vertex_code(), precompute_environment_fragment_code()); precompute_cubemap(environment->cubemap, environment->emission_tex->texture, program, size, 1, environment->emission); clear_program(program); } -void init_envlight(gui_environment* environment) { +void init_envlight(shade_environment* environment) { // precompute irradiance map auto diffuse_program_guard = make_unique(); auto diffuse_program = diffuse_program_guard.get(); auto vert = precompute_cubemap_vertex_code(); auto frag = precompute_irradiance_fragment_code(); - init_program(diffuse_program, vert, frag); + set_program(diffuse_program, vert, frag); precompute_cubemap( environment->envlight_diffuse, environment->cubemap, diffuse_program, 64); clear_program(diffuse_program); @@ -762,7 +780,7 @@ void init_envlight(gui_environment* environment) { // bake specular map auto specular_program_guard = make_unique(); auto specular_program = specular_program_guard.get(); - init_program(specular_program, precompute_cubemap_vertex_code(), + set_program(specular_program, precompute_cubemap_vertex_code(), precompute_reflections_fragment_code()); precompute_cubemap(environment->envlight_specular, environment->cubemap, specular_program, 256, 6); diff --git a/libs/yocto_gui/yocto_draw.h b/libs/yocto_gui/yocto_draw.h index 0876c088d..10b50a9a8 100644 --- a/libs/yocto_gui/yocto_draw.h +++ b/libs/yocto_gui/yocto_draw.h @@ -53,7 +53,7 @@ using std::vector; namespace yocto { // Opengl caemra -struct gui_camera { +struct shade_camera { frame3f frame = identity3x4f; float lens = 0.050; float aspect = 1.000; @@ -65,73 +65,73 @@ struct gui_camera { }; // Opengl texture -struct gui_texture { +struct shade_texture { // shape properties ogl_texture* texture = new ogl_texture{}; // Disable copy construction - gui_texture() = default; - gui_texture(const gui_texture&) = delete; - gui_texture& operator=(const gui_texture&) = delete; + shade_texture() = default; + shade_texture(const shade_texture&) = delete; + shade_texture& operator=(const shade_texture&) = delete; // Cleanup - ~gui_texture(); + ~shade_texture(); }; // Opengl material -struct gui_material { +struct shade_material { // material - vec3f emission = {0, 0, 0}; - vec3f color = {0, 0, 0}; - float metallic = 0; - float roughness = 0; - float specular = 0; - float opacity = 1; - gui_texture* emission_tex = nullptr; - gui_texture* color_tex = nullptr; - gui_texture* metallic_tex = nullptr; - gui_texture* roughness_tex = nullptr; - gui_texture* specular_tex = nullptr; - gui_texture* opacity_tex = nullptr; - gui_texture* normal_tex = nullptr; + vec3f emission = {0, 0, 0}; + vec3f color = {0, 0, 0}; + float metallic = 0; + float roughness = 0; + float specular = 0; + float opacity = 1; + shade_texture* emission_tex = nullptr; + shade_texture* color_tex = nullptr; + shade_texture* metallic_tex = nullptr; + shade_texture* roughness_tex = nullptr; + shade_texture* specular_tex = nullptr; + shade_texture* opacity_tex = nullptr; + shade_texture* normal_tex = nullptr; + bool unlit = false; }; -struct gui_shape { +struct shade_shape { // shape properties ogl_shape* shape = new ogl_shape{}; // Disable copy construction - gui_shape() = default; - gui_shape(const gui_shape&) = delete; - gui_shape& operator=(const gui_shape&) = delete; + shade_shape() = default; + shade_shape(const shade_shape&) = delete; + shade_shape& operator=(const shade_shape&) = delete; // Cleanup - ~gui_shape(); + ~shade_shape(); }; // Shading type -enum struct gui_shading_type { constant = 0, shaded }; +enum struct shade_shading_type { constant = 0, shaded }; // Opengl instance -struct gui_instance { +struct shade_instance { // instance properties - frame3f frame = identity3x4f; - gui_shape* shape = nullptr; - gui_material* material = nullptr; - bool hidden = false; - bool highlighted = false; - gui_shading_type shading = gui_shading_type::shaded; + frame3f frame = identity3x4f; + shade_shape* shape = nullptr; + shade_material* material = nullptr; + bool hidden = false; + bool highlighted = false; }; // Opengl environment -struct gui_environment { +struct shade_environment { // environment properties - frame3f frame = identity3x4f; - vec3f emission = {1, 1, 1}; - gui_texture* emission_tex = nullptr; + frame3f frame = identity3x4f; + vec3f emission = {1, 1, 1}; + shade_texture* emission_tex = nullptr; // drawing data - gui_shape* shape = new gui_shape{}; + shade_shape* shape = new shade_shape{}; ogl_cubemap* cubemap = new ogl_cubemap{}; // envlight precomputed data @@ -140,23 +140,23 @@ struct gui_environment { ogl_texture* envlight_brdflut = new ogl_texture{}; // Disable copy construction - gui_environment() = default; - gui_environment(const gui_environment&) = delete; - gui_environment& operator=(const gui_environment&) = delete; + shade_environment() = default; + shade_environment(const shade_environment&) = delete; + shade_environment& operator=(const shade_environment&) = delete; // Cleanup - ~gui_environment(); + ~shade_environment(); }; // Opengl scene -struct gui_scene { +struct shade_scene { // scene objects - vector cameras = {}; - vector instances = {}; - vector shapes = {}; - vector materials = {}; - vector textures = {}; - vector environments = {}; + vector cameras = {}; + vector instances = {}; + vector shapes = {}; + vector materials = {}; + vector textures = {}; + vector environments = {}; // programs ogl_program* environment_program = new ogl_program{}; @@ -164,180 +164,189 @@ struct gui_scene { ogl_program* envlight_program = new ogl_program{}; // disable copy construction - gui_scene() = default; - gui_scene(const gui_scene&) = delete; - gui_scene& operator=(const gui_scene&) = delete; + shade_scene() = default; + shade_scene(const shade_scene&) = delete; + shade_scene& operator=(const shade_scene&) = delete; // cleanup - ~gui_scene(); + ~shade_scene(); }; // Shading type -enum struct gui_lighting_type { +enum struct shade_lighting_type { envlight, camlight, }; // Shading name -const auto gui_lighting_names = vector{"envlight", "camlight"}; +const auto shade_lighting_names = vector{"envlight", "camlight"}; // Draw options -struct gui_scene_params { - int resolution = 1280; - bool wireframe = false; - gui_lighting_type lighting = gui_lighting_type::camlight; - float exposure = 0; - float gamma = 2.2f; - bool faceted = false; - bool double_sided = true; - bool non_rigid_frames = true; - float near = 0.01f; - float far = 10000.0f; - vec4f background = vec4f{0.15f, 0.15f, 0.15f, 1.0f}; +struct shade_params { + int resolution = 1280; + bool wireframe = false; + shade_lighting_type lighting = shade_lighting_type::camlight; + float exposure = 0; + float gamma = 2.2f; + bool faceted = false; + bool double_sided = true; + bool non_rigid_frames = true; + float near = 0.01f; + float far = 10000.0f; + vec4f background = vec4f{0.15f, 0.15f, 0.15f, 1.0f}; }; // Initialize an OpenGL scene -void init_scene(gui_scene* scene); -bool is_initialized(const gui_scene* scene); +void init_scene(shade_scene* scene); +bool is_initialized(const shade_scene* scene); // Initialize data for environment lighting -void init_environments(gui_scene* scene, bool precompute_envlight = true); +void init_environments(shade_scene* scene, bool precompute_envlight = true); + +// Check if we have an envlight +bool has_envlight(const shade_scene* scene); // Clear an OpenGL scene -void clear_scene(gui_scene* scene); +void clear_scene(shade_scene* scene); // old interface -[[deprecated]] void init_scene(gui_scene* scene, gui_texture* environment_tex, - const vec3f& environment_emission); +[[deprecated]] void init_scene(shade_scene* scene, + shade_texture* environment_tex, const vec3f& environment_emission); // add scene elements -gui_camera* add_camera(gui_scene* scene); -gui_texture* add_texture(gui_scene* scene); -gui_material* add_material(gui_scene* scene); -gui_shape* add_shape(gui_scene* scene); -gui_instance* add_instance(gui_scene* scene); -gui_environment* add_environment(gui_scene* scene); +shade_camera* add_camera(shade_scene* scene); +shade_texture* add_texture(shade_scene* scene); +shade_material* add_material(shade_scene* scene); +shade_shape* add_shape(shade_scene* scene); +shade_instance* add_instance(shade_scene* scene); +shade_environment* add_environment(shade_scene* scene); // camera properties -void set_frame(gui_camera* camera, const frame3f& frame); -void set_lens(gui_camera* camera, float lens, float aspect, float film); -void set_nearfar(gui_camera* camera, float near, float far); +void set_frame(shade_camera* camera, const frame3f& frame); +void set_lens(shade_camera* camera, float lens, float aspect, float film); +void set_nearfar(shade_camera* camera, float near, float far); // check if initialized -bool is_initialized(const gui_texture* texture); +bool is_initialized(const shade_texture* texture); // clear texture -void clear_texture(gui_texture* texture); +void clear_texture(shade_texture* texture); // set texture -void set_texture(gui_texture* texture, const image& img, +void set_texture(shade_texture* texture, const image& img, bool as_srgb = true, bool linear = true, bool mipmap = true); -void set_texture(gui_texture* texture, const image& img, +void set_texture(shade_texture* texture, const image& img, bool as_float = false, bool linear = true, bool mipmap = true); -void set_texture(gui_texture* texture, const image& img, +void set_texture(shade_texture* texture, const image& img, bool as_srgb = true, bool linear = true, bool mipmap = true); -void set_texture(gui_texture* texture, const image& img, +void set_texture(shade_texture* texture, const image& img, bool as_float = false, bool linear = true, bool mipmap = true); -void set_texture(gui_texture* texture, const image& img, +void set_texture(shade_texture* texture, const image& img, bool as_srgb = true, bool linear = true, bool mipmap = true); -void set_texture(gui_texture* texture, const image& img, +void set_texture(shade_texture* texture, const image& img, bool as_float = false, bool linear = true, bool mipmap = true); // material properties -void set_emission(gui_material* material, const vec3f& emission, - gui_texture* emission_tex = nullptr); -void set_color(gui_material* material, const vec3f& color, - gui_texture* color_tex = nullptr); -void set_metallic(gui_material* material, float metallic, - gui_texture* metallic_tex = nullptr); -void set_roughness(gui_material* material, float roughness, - gui_texture* roughness_tex = nullptr); -void set_specular(gui_material* material, float specular, - gui_texture* specular_tex = nullptr); -void set_opacity( - gui_material* material, float opacity, gui_texture* opacity_tex = nullptr); -void set_normalmap(gui_material* material, gui_texture* normal_tex); +void set_emission(shade_material* material, const vec3f& emission, + shade_texture* emission_tex = nullptr); +void set_color(shade_material* material, const vec3f& color, + shade_texture* color_tex = nullptr); +void set_metallic(shade_material* material, float metallic, + shade_texture* metallic_tex = nullptr); +void set_roughness(shade_material* material, float roughness, + shade_texture* roughness_tex = nullptr); +void set_specular(shade_material* material, float specular, + shade_texture* specular_tex = nullptr); +void set_opacity(shade_material* material, float opacity, + shade_texture* opacity_tex = nullptr); +void set_normalmap(shade_material* material, shade_texture* normal_tex); +void set_unlit(shade_material* material, bool unlit); // cheeck if initialized -bool is_initialized(const gui_shape* shape); +bool is_initialized(const shade_shape* shape); // clear -void clear_shape(gui_shape* shape); +void clear_shape(shade_shape* shape); // shape properties -void set_points(gui_shape* shape, const vector& points); -void set_lines(gui_shape* shape, const vector& lines); -void set_triangles(gui_shape* shape, const vector& triangles); -void set_quads(gui_shape* shape, const vector& quads); -void set_positions(gui_shape* shape, const vector& positions); -void set_normals(gui_shape* shape, const vector& normals); -void set_texcoords(gui_shape* shape, const vector& texcoords); -void set_colors(gui_shape* shape, const vector& colors); -void set_tangents(gui_shape* shape, const vector& tangents); -void set_instance_from(gui_shape* shape, const vector& froms); -void set_instance_to(gui_shape* shape, const vector& tos); +void set_points(shade_shape* shape, const vector& points); +void set_lines(shade_shape* shape, const vector& lines); +void set_triangles(shade_shape* shape, const vector& triangles); +void set_quads(shade_shape* shape, const vector& quads); +void set_positions(shade_shape* shape, const vector& positions); +void set_normals(shade_shape* shape, const vector& normals); +void set_texcoords(shade_shape* shape, const vector& texcoords); +void set_colors(shade_shape* shape, const vector& colors); +void set_tangents(shade_shape* shape, const vector& tangents); +void set_instance_from(shade_shape* shape, const vector& froms); +void set_instance_to(shade_shape* shape, const vector& tos); // get shaoe properties -ogl_arraybuffer* get_positions(gui_shape* shape); -ogl_arraybuffer* get_normals(gui_shape* shape); -ogl_arraybuffer* get_texcoords(gui_shape* shape); -ogl_arraybuffer* get_colors(gui_shape* shape); -ogl_arraybuffer* get_tangents(gui_shape* shape); +const ogl_arraybuffer* get_positions(const shade_shape* shape); +const ogl_arraybuffer* get_normals(const shade_shape* shape); +const ogl_arraybuffer* get_texcoords(const shade_shape* shape); +const ogl_arraybuffer* get_colors(const shade_shape* shape); +const ogl_arraybuffer* get_tangents(const shade_shape* shape); // instance properties -void set_frame(gui_instance* instance, const frame3f& frame); -void set_shape(gui_instance* instance, gui_shape* shape); -void set_material(gui_instance* instance, gui_material* material); -void set_hidden(gui_instance* instance, bool hidden); -void set_highlighted(gui_instance* instance, bool highlighted); +void set_frame(shade_instance* instance, const frame3f& frame); +void set_shape(shade_instance* instance, shade_shape* shape); +void set_material(shade_instance* instance, shade_material* material); +void set_hidden(shade_instance* instance, bool hidden); +void set_highlighted(shade_instance* instance, bool highlighted); // check if initialized -bool is_initialized(const gui_environment* environment); +bool is_initialized(const shade_environment* environment); // clear environment -void clear_environment(gui_environment* environment); +void clear_environment(shade_environment* environment); // environment properties -void set_frame(gui_environment* environment, const frame3f& frame); -void set_emission(gui_environment* environment, const vec3f& emission, - gui_texture* emission_tex = nullptr); +void set_frame(shade_environment* environment, const frame3f& frame); +void set_emission(shade_environment* environment, const vec3f& emission, + shade_texture* emission_tex = nullptr); // shortcuts -gui_camera* add_camera(gui_scene* scene, const frame3f& frame, float lens, - float aspect, float film = 0.036, float near = 0.001, float far = 10000); -gui_material* add_material(gui_scene* scene, const vec3f& emission, - const vec3f& color, float specular, float metallic, float roughness, - gui_texture* emission_tex = nullptr, gui_texture* color_tex = nullptr, - gui_texture* specular_tex = nullptr, gui_texture* metallic_tex = nullptr, - gui_texture* roughness_tex = nullptr, gui_texture* normalmap_tex = nullptr); -gui_shape* add_shape(gui_scene* scene, const vector& points, - const vector& lines, const vector& triangles, - const vector& quads, const vector& positions, - const vector& normals, const vector& texcoords, - const vector& colors, bool edges = false); -gui_instance* add_instance(gui_scene* scene, const frame3f& frame, - gui_shape* shape, gui_material* material, bool hidden = false, - bool highlighted = false); -gui_environment* add_environment(gui_scene* scene, const frame3f& frame, - const vec3f& emission, gui_texture* emission_tex = nullptr); +shade_camera* add_camera(shade_scene* scene, const frame3f& frame, float lens, + float aspect, float film = 0.036, float near = 0.001, float far = 10000); +shade_material* add_material(shade_scene* scene, const vec3f& emission, + const vec3f& color, float specular, float metallic, float roughness, + shade_texture* emission_tex = nullptr, shade_texture* color_tex = nullptr, + shade_texture* specular_tex = nullptr, + shade_texture* metallic_tex = nullptr, + shade_texture* roughness_tex = nullptr, + shade_texture* normalmap_tex = nullptr); +shade_shape* add_shape(shade_scene* scene, const vector& points, + const vector& lines, const vector& triangles, + const vector& quads, const vector& positions, + const vector& normals, const vector& texcoords, + const vector& colors, bool edges = false); +shade_instance* add_instance(shade_scene* scene, const frame3f& frame, + shade_shape* shape, shade_material* material, bool hidden = false, + bool highlighted = false); +shade_environment* add_environment(shade_scene* scene, const frame3f& frame, + const vec3f& emission, shade_texture* emission_tex = nullptr); // internal drawing functions -struct gui_scene_view { - frame3f camera_frame = {}; - mat4f view_matrix = {}; - mat4f projection_matrix = {}; - gui_scene_params params = {}; +struct shade_view { + frame3f camera_frame = {}; + mat4f view_matrix = {}; + mat4f projection_matrix = {}; }; -void set_scene_view_uniforms(ogl_program* program, const gui_scene_view& view); +void set_view_uniforms(ogl_program* program, const shade_view& view); void set_instance_uniforms(ogl_program* program, const frame3f& frame, - const gui_shape* shape, const gui_material* material, int shading_type = 0, - bool double_sided = true, bool non_rigid_frames = false); -void set_eyelight_uniforms(ogl_program* program, const gui_scene_view& view); -void set_ibl_uniforms(ogl_program* program, const gui_scene* scene); - -void draw_instances(gui_scene* scene, const gui_scene_view& view); -void draw_environment(gui_scene* scene, const gui_scene_view& view); - -void draw_scene(gui_scene* scene, gui_camera* camera, const vec4i& viewport, - const gui_scene_params& params); + const shade_shape* shape, const shade_material* material, + const shade_params& params); +void set_camlight_uniforms( + ogl_program* program, const shade_scene* scene, const shade_view& view); +void set_envlight_uniforms( + ogl_program* program, const shade_scene* scene, const shade_view& view); + +void draw_instances( + shade_scene* scene, const shade_view& view, const shade_params& params); +void draw_environments( + shade_scene* scene, const shade_view& view, const shade_params& params); + +void draw_scene(shade_scene* scene, shade_camera* camera, const vec4i& viewport, + const shade_params& params); // read-only access to defualt shader code const char* draw_instances_vertex_code(); diff --git a/libs/yocto_gui/yocto_opengl.cpp b/libs/yocto_gui/yocto_opengl.cpp index 40cb218c5..750f94a65 100644 --- a/libs/yocto_gui/yocto_opengl.cpp +++ b/libs/yocto_gui/yocto_opengl.cpp @@ -577,7 +577,7 @@ void set_elementbuffer( } // initialize program -bool init_program(ogl_program* program, const string& vertex, +bool set_program(ogl_program* program, const string& vertex, const string& fragment, string& error, string& errorlog) { // error auto program_error = [&error, &errorlog, program]( @@ -653,17 +653,20 @@ bool init_program(ogl_program* program, const string& vertex, return true; } +// initialize program +bool set_program(ogl_program* program, const string& vertex, + const string& fragment, string& error) { + auto errorlog = string{}; + return set_program(program, vertex, fragment, error, errorlog); +} + // initialize program, print eventual errors to stdout -bool init_program(ogl_program* program, const string& vertex, +bool set_program(ogl_program* program, const string& vertex, const string& fragment, bool exceptions) { auto error = string{}; auto errorlog = string{}; - if (!init_program(program, vertex, fragment, error, errorlog)) { - printf("error: %s\n", error.c_str()); - printf("errorlog: %s\n", errorlog.c_str()); - if (exceptions) { - throw std::runtime_error{"error initalizing OpenGL program"}; - } + if (!set_program(program, vertex, fragment, error, errorlog)) { + if (exceptions) throw std::runtime_error{error}; return false; } return true; @@ -839,7 +842,7 @@ void set_uniform(const ogl_program* program, const char* name, get_uniform_location(program, name_on), cubemap, unit); } -void init_framebuffer(ogl_framebuffer* framebuffer, const vec2i& size) { +void set_framebuffer(ogl_framebuffer* framebuffer, const vec2i& size) { if (!framebuffer->framebuffer_id) { glGenFramebuffers(1, &framebuffer->framebuffer_id); } @@ -924,12 +927,6 @@ ogl_shape::~ogl_shape() { void bind_shape(const ogl_shape* shape) { glBindVertexArray(shape->shape_id); } -void init_shape(ogl_shape* shape) { - if (shape->shape_id) glDeleteVertexArrays(1, &shape->shape_id); - glGenVertexArrays(1, &shape->shape_id); - assert_ogl_error(); -} - bool is_initialized(const ogl_shape* shape) { return shape->shape_id != 0; } // Clear an OpenGL shape @@ -947,11 +944,12 @@ void clear_shape(ogl_shape* shape) { template void set_vertex_buffer_impl( ogl_shape* shape, const vector& data, int location) { + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); while (shape->vertex_buffers.size() <= location) { shape->vertex_buffers.push_back(new ogl_arraybuffer{}); } set_arraybuffer(shape->vertex_buffers[location], data, false); - bind_shape(shape); + glBindVertexArray(shape->shape_id); auto buffer = shape->vertex_buffers[location]; assert_ogl_error(); glBindBuffer(GL_ARRAY_BUFFER, buffer->buffer_id); @@ -963,43 +961,52 @@ void set_vertex_buffer_impl( void set_vertex_buffer( ogl_shape* shape, const vector& values, int location) { + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); set_vertex_buffer_impl(shape, values, location); } void set_vertex_buffer( ogl_shape* shape, const vector& values, int location) { + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); set_vertex_buffer_impl(shape, values, location); } void set_vertex_buffer( ogl_shape* shape, const vector& values, int location) { + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); set_vertex_buffer_impl(shape, values, location); } void set_vertex_buffer( ogl_shape* shape, const vector& values, int location) { + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); set_vertex_buffer_impl(shape, values, location); } void set_vertex_buffer(ogl_shape* shape, float value, int location) { - bind_shape(shape); + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); + glBindVertexArray(shape->shape_id); glVertexAttrib1f(location, value); assert_ogl_error(); } void set_vertex_buffer(ogl_shape* shape, const vec2f& value, int location) { - bind_shape(shape); + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); + glBindVertexArray(shape->shape_id); glVertexAttrib2f(location, value.x, value.y); assert_ogl_error(); } void set_vertex_buffer(ogl_shape* shape, const vec3f& value, int location) { - bind_shape(shape); + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); + glBindVertexArray(shape->shape_id); glVertexAttrib3f(location, value.x, value.y, value.z); assert_ogl_error(); } void set_vertex_buffer(ogl_shape* shape, const vec4f& value, int location) { - bind_shape(shape); + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); + glBindVertexArray(shape->shape_id); glVertexAttrib4f(location, value.x, value.y, value.z, value.w); assert_ogl_error(); } void set_instance_buffer(ogl_shape* shape, int location, bool is_instance) { + if (!shape->shape_id) glGenVertexArrays(1, &shape->shape_id); bind_shape(shape); if (is_instance) { glVertexAttribDivisor(location, 1); @@ -1068,7 +1075,6 @@ void set_cube_shape(ogl_shape* shape) { {4, 5, 1}, {5, 6, 2}, {2, 6, 7}, {0, 3, 7} }; // clang-format on - init_shape(shape); set_vertex_buffer(shape, positions, 0); set_index_buffer(shape, triangles); } @@ -1082,7 +1088,6 @@ void set_quad_shape(ogl_shape* shape) { {0, 1, 3}, {3, 2, 1} }; // clang-format on - init_shape(shape); set_vertex_buffer(shape, positions, 0); set_index_buffer(shape, triangles); } @@ -1165,7 +1170,7 @@ bool is_initialized(const ogl_image* image) { // init image program bool init_image(ogl_image* image) { if (is_initialized(image)) return true; - if (!init_program(image->program, glimage_vertex, glimage_fragment)) + if (!set_program(image->program, glimage_vertex, glimage_fragment)) return false; set_quad_shape(image->quad); return true; diff --git a/libs/yocto_gui/yocto_opengl.h b/libs/yocto_gui/yocto_opengl.h index d315155f4..88abcf6e1 100644 --- a/libs/yocto_gui/yocto_opengl.h +++ b/libs/yocto_gui/yocto_opengl.h @@ -146,13 +146,6 @@ void set_cubemap(ogl_cubemap* cubemap, int size, int num_channels, const array& img, bool as_float = false, bool linear = true, bool mipmap = true); -template -void set_cubemap(ogl_cubemap* cubemap, int size, int num_channels, - bool as_float = false, bool linear = true, bool mipmap = true) { - auto img = array{0, 0, 0, 0, 0, 0}; - set_cubemap(cubemap, size, num_channels, img, as_float, mipmap); -} - // check if cubemap is initialized bool is_initialized(const ogl_cubemap* cubemap); @@ -269,9 +262,11 @@ struct ogl_program { }; // initialize program -bool init_program(ogl_program* program, const string& vertex, +bool set_program(ogl_program* program, const string& vertex, + const string& fragment, string& error); +bool set_program(ogl_program* program, const string& vertex, const string& fragment, string& error, string& errorlog); -bool init_program(ogl_program* program, const string& vertex, +bool set_program(ogl_program* program, const string& vertex, const string& fragment, bool exceptions = true); bool is_initialized(const ogl_program* program); @@ -344,7 +339,7 @@ struct ogl_framebuffer { static inline uint bound_framebuffer_id = 0; }; -void init_framebuffer(ogl_framebuffer* framebuffer, const vec2i& size); +void set_framebuffer(ogl_framebuffer* framebuffer, const vec2i& size); void set_framebuffer_texture(const ogl_framebuffer* framebuffer, const ogl_texture* texture, uint mipmap_level = 0); @@ -392,17 +387,6 @@ struct ogl_shape { ~ogl_shape(); }; -[[deprecated]] void init_shape(ogl_shape* shape); - -// check if shape is initialized -bool is_initialized(const ogl_shape* shape); - -// clear buffer -void clear_shape(ogl_shape* shape); - -// bind shape -void bind_shape(const ogl_shape* shape); - // set vertex buffer void set_vertex_buffer( ogl_shape* shape, const vector& values, int location); @@ -427,6 +411,15 @@ void set_index_buffer(ogl_shape* shape, const vector& indices); void set_index_buffer(ogl_shape* shape, const vector& indices); void set_index_buffer(ogl_shape* shape, const vector& indices); +// check if shape is initialized +bool is_initialized(const ogl_shape* shape); + +// clear buffer +void clear_shape(ogl_shape* shape); + +// bind shape +void bind_shape(const ogl_shape* shape); + // draw shape void draw_shape(const ogl_shape* shape);