Skip to content

Commit

Permalink
Gui initial support for multiple environments (#1054)
Browse files Browse the repository at this point in the history
  • Loading branch information
xelatihy authored Aug 27, 2020
1 parent 1fee772 commit 2a00ef2
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 110 deletions.
19 changes: 11 additions & 8 deletions apps/ysceneview/ysceneview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene,
(int)ioscene->textures.size() + (int)ioscene->shapes.size() +
(int)ioscene->instances.size()};

// init scene
init_scene(glscene);

// camera
auto camera_map = unordered_map<sceneio_camera*, gui_camera*>{};
camera_map[nullptr] = nullptr;
Expand Down Expand Up @@ -208,16 +211,16 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene,
set_material(instance, material_map.at(ioinstance->material));
}

gui_texture* environment_tex = nullptr;
auto environment_emission = vec3f{0, 0, 0};
if (!ioscene->environments.empty()) {
auto environment = ioscene->environments[0];
environment_tex = texture_map[environment->emission_tex];
environment_emission = environment->emission;
// environments
for (auto ioenvironment : ioscene->environments) {
auto environment = add_environment(glscene);
set_frame(environment, ioenvironment->frame);
set_emission(environment, ioenvironment->emission,
texture_map.at(ioenvironment->emission_tex));
}

// init scene
init_scene(glscene, environment_tex, environment_emission);
// init environments
init_environments(glscene);

// done
if (progress_cb) progress_cb("convert done", progress.x++, progress.y);
Expand Down
19 changes: 11 additions & 8 deletions apps/ysceneviews/ysceneviews.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene,
(int)ioscene->textures.size() + (int)ioscene->shapes.size() +
(int)ioscene->instances.size()};

// init scene
init_scene(glscene);

// camera
auto camera_map = unordered_map<sceneio_camera*, gui_camera*>{};
camera_map[nullptr] = nullptr;
Expand Down Expand Up @@ -169,16 +172,16 @@ void init_glscene(gui_scene* glscene, sceneio_scene* ioscene,
set_material(globject, material_map.at(ioobject->material));
}

gui_texture* environment_tex = nullptr;
auto environment_emission = vec3f{0, 0, 0};
if (!ioscene->environments.empty()) {
auto environment = ioscene->environments[0];
environment_tex = texture_map[environment->emission_tex];
environment_emission = environment->emission;
// environments
for (auto ioenvironment : ioscene->environments) {
auto environment = add_environment(glscene);
set_frame(environment, ioenvironment->frame);
set_emission(environment, ioenvironment->emission,
texture_map.at(ioenvironment->emission_tex));
}

// init scene
init_scene(glscene, environment_tex, environment_emission);
// init environments
init_environments(glscene);

// done
if (progress_cb) progress_cb("convert done", progress.x++, progress.y);
Expand Down
6 changes: 3 additions & 3 deletions apps/yshapeview/yshapeview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ void init_glscene(app_state* app, gui_scene* glscene, generic_shape* ioshape,
// handle progress
auto progress = vec2i{0, 4};

// init scene
init_scene(glscene);

// compute bounding box
auto bbox = invalidb3f;
for (auto& pos : ioshape->positions) bbox = merge(bbox, pos);
Expand Down Expand Up @@ -248,9 +251,6 @@ void init_glscene(app_state* app, gui_scene* glscene, generic_shape* ioshape,
glscene, identity3x4f, vertices_shape, glmaterialv, true);
points_instance->shading = gui_shading_type::constant;

// init scene
init_scene(glscene);

// override eyelight vertex shader
auto vert = draw_instanced_vertex_code();
auto frag = draw_instances_eyelight_fragment_code();
Expand Down
149 changes: 98 additions & 51 deletions libs/yocto_gui/yocto_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,9 @@ gui_scene::~gui_scene() {
for (auto shape : shapes) delete shape;
for (auto material : materials) delete material;
for (auto texture : textures) delete texture;
delete environment_shape;
delete environment_cubemap;
for (auto instance : instances) delete instance;
for (auto environment : environments) delete environment;
delete environment_program;
delete diffuse_cubemap;
delete specular_cubemap;
delete brdf_lut;
delete camlight_program;
delete envlight_program;
}
Expand All @@ -175,42 +172,54 @@ 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_scene* scene,
const gui_texture* environment_tex, const vec3f& environment_emission);
static void init_environment(gui_environment* environment);
static void init_envlight(gui_environment* environment);

// Initialize an OpenGL scene
void init_scene(gui_scene* scene, const gui_texture* environment_tex,
const vec3f& environment_emission) {
void init_scene(gui_scene* scene) {
if (is_initialized(scene->camlight_program)) return;
auto error = ""s, errorlog = ""s;
auto vert = draw_instances_vertex_code();
auto frag = draw_instances_eyelight_fragment_code();
init_program(scene->camlight_program, vert, frag, error, errorlog);

if (environment_tex && environment_emission != vec3f{0, 0, 0}) {
init_environment(scene, environment_tex, environment_emission);
init_ibl_data(scene);
}
init_program(scene->camlight_program, draw_instances_vertex_code(),
draw_instances_eyelight_fragment_code(), error, errorlog);
init_program(scene->envlight_program, draw_instances_vertex_code(),
draw_instances_ibl_fragment_code(), error, errorlog);
init_program(scene->environment_program, precompute_cubemap_vertex_code(),
draw_enivronment_fragment_code());
}

bool is_initialized(gui_scene* scene) {
return scene && is_initialized(scene->camlight_program);
}

// Initialize data for environment lighting
void init_environments(gui_scene* scene, bool precompute_envlight) {
for (auto environment : scene->environments) {
init_environment(environment);
if (precompute_envlight) init_envlight(environment);
}
}

// Clear an OpenGL scene
void clear_scene(gui_scene* scene) {
for (auto texture : scene->textures) clear_texture(texture);
for (auto shape : scene->shapes) clear_shape(shape);
clear_shape(scene->environment_shape);
clear_cubemap(scene->environment_cubemap);
for (auto environment : scene->environments) clear_environment(environment);
clear_program(scene->environment_program);
clear_cubemap(scene->diffuse_cubemap);
clear_cubemap(scene->specular_cubemap);
clear_texture(scene->brdf_lut);
clear_program(scene->camlight_program);
clear_program(scene->envlight_program);
}

// Initialize an OpenGL scene
[[deprecated]] void init_scene(gui_scene* scene, gui_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);
}
init_scene(scene);
init_environments(scene);
}

// add camera
gui_camera* add_camera(gui_scene* scene) {
return scene->cameras.emplace_back(new gui_camera{});
Expand Down Expand Up @@ -366,6 +375,42 @@ gui_shape* add_shape(gui_scene* scene, const vector<int>& points,
return shape;
}

// cleanup
gui_environment::~gui_environment() {
delete shape;
delete cubemap;
delete envlight_diffuse;
delete envlight_specular;
delete envlight_brdflut;
}

// cheeck if initialized
bool is_initialized(const gui_environment* environment) {
return is_initialized(environment->shape);
}

// clear
void clear_environment(gui_environment* environment) {
clear_shape(environment->shape);
clear_cubemap(environment->cubemap);
clear_cubemap(environment->envlight_diffuse);
clear_cubemap(environment->envlight_specular);
clear_texture(environment->envlight_brdflut);
}

// environment properties
gui_environment* add_environment(gui_scene* scene) {
return scene->environments.emplace_back(new gui_environment{});
}
void set_frame(gui_environment* environment, const frame3f& frame) {
environment->frame = frame;
}
void set_emission(gui_environment* environment, const vec3f& emission,
gui_texture* emission_tex) {
environment->emission = emission;
environment->emission_tex = emission_tex;
}

// shortcuts
gui_camera* add_camera(gui_scene* scene, const frame3f& frame, float lens,
float aspect, float film, float near, float far) {
Expand Down Expand Up @@ -401,6 +446,14 @@ 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) {
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) {
set_uniform(program, "eye", view.camera_frame.o);
set_uniform(program, "view", view.view_matrix);
Expand Down Expand Up @@ -469,17 +522,16 @@ void set_instance_uniforms(ogl_program* program, const frame3f& frame,

static void draw_shape(gui_shape* shape) { draw_shape(shape->shape); }

void draw_environment(gui_scene* scene, const gui_scene_view& view) {
void draw_environments(gui_scene* scene, const gui_scene_view& view) {
auto program = scene->environment_program;
if (program->program_id == 0) return;

if (!is_initialized(program)) return;
bind_program(program);

set_scene_view_uniforms(program, view);
set_uniform(program, "environment", scene->environment_cubemap, 0);

draw_shape(scene->environment_shape);

for (auto environment : scene->environments) {
if (!is_initialized(environment->cubemap)) continue;
set_uniform(program, "environment", environment->cubemap, 0);
draw_shape(environment->shape);
}
unbind_program();
}

Expand Down Expand Up @@ -521,14 +573,16 @@ void set_eyelight_uniforms(ogl_program* program, const gui_scene_view& view) {
}

void set_ibl_uniforms(ogl_program* program, const gui_scene* scene) {
set_uniform(program, "irradiance_cubemap", scene->diffuse_cubemap, 6);
set_uniform(program, "reflection_cubemap", scene->specular_cubemap, 7);
set_uniform(program, "brdf_lut", scene->brdf_lut, 8);
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 (is_initialized(scene->environment_cubemap) &&
if (!scene->environments.empty() &&
is_initialized(scene->environments.front()->cubemap) &&
view.params.lighting == gui_lighting_type::envlight) {
program = scene->envlight_program;
}
Expand Down Expand Up @@ -582,7 +636,7 @@ void draw_scene(gui_scene* scene, gui_camera* camera, const vec4i& viewport,

auto view = make_scene_view(camera, viewport, params);
draw_instances(scene, view);
draw_environment(scene, view);
draw_environments(scene, view);
}

// image based lighting
Expand Down Expand Up @@ -680,33 +734,30 @@ inline void precompute_specular_brdf_texture(ogl_texture* texture) {
clear_shape(screen_quad);
}

static void init_environment(gui_scene* scene,
const gui_texture* environment_tex, const vec3f& environment_emission) {
static void init_environment(gui_environment* environment) {
// init program and shape for drawing the environment
set_cube_shape(scene->environment_shape->shape);
init_program(scene->environment_program, precompute_cubemap_vertex_code(),
draw_enivronment_fragment_code());
set_cube_shape(environment->shape->shape);

// precompute cubemap from environment texture
auto size = environment_tex->texture->size.y;
auto size = environment->emission_tex->texture->size.y;
auto program_guard = make_unique<ogl_program>();
auto program = program_guard.get();
init_program(program, precompute_cubemap_vertex_code(),
precompute_environment_fragment_code());
precompute_cubemap(scene->environment_cubemap, environment_tex->texture,
program, size, 1, environment_emission);
precompute_cubemap(environment->cubemap, environment->emission_tex->texture,
program, size, 1, environment->emission);
clear_program(program);
}

void init_ibl_data(gui_scene* scene) {
void init_envlight(gui_environment* environment) {
// precompute irradiance map
auto diffuse_program_guard = make_unique<ogl_program>();
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);
precompute_cubemap(
scene->diffuse_cubemap, scene->environment_cubemap, diffuse_program, 64);
environment->envlight_diffuse, environment->cubemap, diffuse_program, 64);
clear_program(diffuse_program);
diffuse_program_guard.release();

Expand All @@ -715,17 +766,13 @@ void init_ibl_data(gui_scene* scene) {
auto specular_program = specular_program_guard.get();
init_program(specular_program, precompute_cubemap_vertex_code(),
precompute_reflections_fragment_code());
precompute_cubemap(scene->specular_cubemap, scene->environment_cubemap,
precompute_cubemap(environment->envlight_specular, environment->cubemap,
specular_program, 256, 6);
clear_program(specular_program);
specular_program_guard.release();

// bake lookup texture for specular brdf
precompute_specular_brdf_texture(scene->brdf_lut);

// init shader for IBL shading
init_program(scene->envlight_program, draw_instances_vertex_code(),
draw_instances_ibl_fragment_code());
precompute_specular_brdf_texture(environment->envlight_brdflut);
}

const char* draw_instances_vertex_code() {
Expand Down
Loading

0 comments on commit 2a00ef2

Please sign in to comment.