Add Containers scene for testing specular maps; name scenes
- Add Scene::name and show it in the scene selector (falls back to "Scene N" when empty; ImGui IDs keep equal names apart) - Add a Containers scene: container2 with its specular map, arranged on a floor as a pyramid, a stack, loose crates and one large crate. Lit by 8 point and 4 spot lights, with the directional light's diffuse and specular turned off - create_textured_material() takes an optional specular map, loaded without the checkerboard fallback like in the OBJ loader - Add create_floor() and use it for the Backpack scene too (same position as before)
This commit is contained in:
108
src/main.cpp
108
src/main.cpp
@@ -105,7 +105,10 @@ Rc<Scene> create_sponza_scene(const Rc<Shader>& shader);
|
|||||||
Rc<Scene> create_car_scene(const Rc<Shader>& shader);
|
Rc<Scene> create_car_scene(const Rc<Shader>& shader);
|
||||||
Rc<Scene> create_backpack_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh);
|
Rc<Scene> create_backpack_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh);
|
||||||
Rc<Scene> create_cubes_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh);
|
Rc<Scene> create_cubes_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh);
|
||||||
Rc<Material> create_textured_material(const Rc<Shader>& shader, const std::string& texture_path);
|
Rc<Scene> create_containers_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh);
|
||||||
|
Entity create_floor(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh, float top_y);
|
||||||
|
Rc<Material> create_textured_material(const Rc<Shader>& shader, const std::string& diffuse_path,
|
||||||
|
const std::string& specular_path = "");
|
||||||
void add_random_lights(Scene& scene, int point_light_count, int spot_light_count, unsigned int seed);
|
void add_random_lights(Scene& scene, int point_light_count, int spot_light_count, unsigned int seed);
|
||||||
|
|
||||||
// Frame
|
// Frame
|
||||||
@@ -210,12 +213,14 @@ std::vector<Rc<Scene>> create_scenes(const Rc<Shader>& shader, const Rc<Mesh>& c
|
|||||||
create_car_scene(shader),
|
create_car_scene(shader),
|
||||||
create_backpack_scene(shader, cube_mesh),
|
create_backpack_scene(shader, cube_mesh),
|
||||||
create_cubes_scene(shader, cube_mesh),
|
create_cubes_scene(shader, cube_mesh),
|
||||||
|
create_containers_scene(shader, cube_mesh),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Rc<Scene> create_sponza_scene(const Rc<Shader>& shader)
|
Rc<Scene> create_sponza_scene(const Rc<Shader>& shader)
|
||||||
{
|
{
|
||||||
auto scene = make_rc<Scene>();
|
auto scene = make_rc<Scene>();
|
||||||
|
scene->name = "Sponza";
|
||||||
|
|
||||||
Entity sponza = load_obj("./assets/sponza/sponza.obj", shader);
|
Entity sponza = load_obj("./assets/sponza/sponza.obj", shader);
|
||||||
sponza.transform.position = {0.0f, -0.5f, 0.0f};
|
sponza.transform.position = {0.0f, -0.5f, 0.0f};
|
||||||
@@ -229,6 +234,7 @@ Rc<Scene> create_sponza_scene(const Rc<Shader>& shader)
|
|||||||
Rc<Scene> create_car_scene(const Rc<Shader>& shader)
|
Rc<Scene> create_car_scene(const Rc<Shader>& shader)
|
||||||
{
|
{
|
||||||
auto scene = make_rc<Scene>();
|
auto scene = make_rc<Scene>();
|
||||||
|
scene->name = "Audi R8";
|
||||||
|
|
||||||
scene->add_entity(load_obj("./assets/audi_r8/Audi_R8_2017.obj", shader));
|
scene->add_entity(load_obj("./assets/audi_r8/Audi_R8_2017.obj", shader));
|
||||||
|
|
||||||
@@ -239,13 +245,10 @@ Rc<Scene> create_car_scene(const Rc<Shader>& shader)
|
|||||||
Rc<Scene> create_backpack_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh)
|
Rc<Scene> create_backpack_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh)
|
||||||
{
|
{
|
||||||
auto scene = make_rc<Scene>();
|
auto scene = make_rc<Scene>();
|
||||||
|
scene->name = "Backpack";
|
||||||
|
|
||||||
scene->add_entity(load_obj("./assets/backpack/backpack.obj", shader, true));
|
scene->add_entity(load_obj("./assets/backpack/backpack.obj", shader, true));
|
||||||
|
scene->add_entity(create_floor(shader, cube_mesh, -2.5f));
|
||||||
Entity floor{cube_mesh, create_textured_material(shader, "./assets/textures/wall.jpg")};
|
|
||||||
floor.transform.position = {0.0f, -3.0f, 0.0f};
|
|
||||||
floor.transform.scale = {20.0f, 1.0f, 20.0f};
|
|
||||||
scene->add_entity(floor);
|
|
||||||
|
|
||||||
add_random_lights(*scene, 4, 4, 37);
|
add_random_lights(*scene, 4, 4, 37);
|
||||||
return scene;
|
return scene;
|
||||||
@@ -254,6 +257,8 @@ Rc<Scene> create_backpack_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_m
|
|||||||
Rc<Scene> create_cubes_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh)
|
Rc<Scene> create_cubes_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh)
|
||||||
{
|
{
|
||||||
auto scene = make_rc<Scene>();
|
auto scene = make_rc<Scene>();
|
||||||
|
scene->name = "Cubes";
|
||||||
|
|
||||||
auto material = create_textured_material(shader, "./assets/textures/container.jpg");
|
auto material = create_textured_material(shader, "./assets/textures/container.jpg");
|
||||||
|
|
||||||
const std::vector<glm::vec3> positions{
|
const std::vector<glm::vec3> positions{
|
||||||
@@ -274,11 +279,88 @@ Rc<Scene> create_cubes_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh
|
|||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rc<Material> create_textured_material(const Rc<Shader>& shader, const std::string& texture_path)
|
// Containers resting on a floor, for testing specular maps: the steel frame
|
||||||
|
// shines, the wood doesn't
|
||||||
|
Rc<Scene> create_containers_scene(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh)
|
||||||
|
{
|
||||||
|
auto scene = make_rc<Scene>();
|
||||||
|
scene->name = "Containers";
|
||||||
|
|
||||||
|
scene->add_entity(create_floor(shader, cube_mesh, -0.5f));
|
||||||
|
|
||||||
|
auto material = create_textured_material(shader, "./assets/textures/container2.png",
|
||||||
|
"./assets/textures/container2_specular.png");
|
||||||
|
|
||||||
|
struct Placement
|
||||||
|
{
|
||||||
|
glm::vec3 position; // Center of the container
|
||||||
|
float yaw_degrees;
|
||||||
|
float size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unit containers on the floor have their center at y = 0
|
||||||
|
const std::vector<Placement> placements{
|
||||||
|
// Pyramid in the middle
|
||||||
|
{{-1.05f, 0.0f, 0.0f}, 0.0f, 1.0f},
|
||||||
|
{{ 0.0f, 0.0f, 0.0f}, 0.0f, 1.0f},
|
||||||
|
{{ 1.05f, 0.0f, 0.0f}, 0.0f, 1.0f},
|
||||||
|
{{-0.56f, 1.0f, 0.0f}, 4.0f, 1.0f},
|
||||||
|
{{ 0.56f, 1.0f, 0.0f}, -3.0f, 1.0f},
|
||||||
|
{{ 0.0f, 2.0f, 0.0f}, 12.0f, 1.0f},
|
||||||
|
|
||||||
|
// Stack of two on the left
|
||||||
|
{{-3.2f, 0.0f, -0.5f}, 15.0f, 1.0f},
|
||||||
|
{{-3.2f, 1.0f, -0.5f}, 35.0f, 1.0f},
|
||||||
|
|
||||||
|
// Loose containers around
|
||||||
|
{{-3.0f, 0.0f, 2.0f}, -20.0f, 1.0f},
|
||||||
|
{{ 2.0f, 0.0f, -2.5f}, 45.0f, 1.0f},
|
||||||
|
{{ 1.5f, 0.0f, 3.0f}, 70.0f, 1.0f},
|
||||||
|
|
||||||
|
// A big one in the back
|
||||||
|
{{-3.5f, 0.5f, -3.5f}, 25.0f, 2.0f},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const Placement& placement : placements) {
|
||||||
|
Entity container{cube_mesh, material};
|
||||||
|
container.transform.position = placement.position;
|
||||||
|
container.transform.set_rotation(glm::radians(placement.yaw_degrees), {0.0f, 1.0f, 0.0f});
|
||||||
|
container.transform.scale = glm::vec3(placement.size);
|
||||||
|
scene->add_entity(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only the local lights shine here, so their highlights are easy to see.
|
||||||
|
// The directional light's ambient stays to keep unlit sides from going black
|
||||||
|
DirectionalLight& sun = scene->light_environment.directional_light;
|
||||||
|
sun.diffuse = glm::vec3(0.0f);
|
||||||
|
sun.specular = glm::vec3(0.0f);
|
||||||
|
|
||||||
|
// More point lights than the other scenes, for more highlights to compare
|
||||||
|
add_random_lights(*scene, 8, 4, 2718);
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 20x20 slab with the wall texture, its top surface at height top_y
|
||||||
|
Entity create_floor(const Rc<Shader>& shader, const Rc<Mesh>& cube_mesh, float top_y)
|
||||||
|
{
|
||||||
|
Entity floor{cube_mesh, create_textured_material(shader, "./assets/textures/wall.jpg")};
|
||||||
|
floor.transform.position = {0.0f, top_y - 0.5f, 0.0f};
|
||||||
|
floor.transform.scale = {20.0f, 1.0f, 20.0f};
|
||||||
|
return floor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rc<Material> create_textured_material(const Rc<Shader>& shader, const std::string& diffuse_path,
|
||||||
|
const std::string& specular_path/* = ""*/)
|
||||||
{
|
{
|
||||||
auto material = make_rc<Material>();
|
auto material = make_rc<Material>();
|
||||||
material->shader = shader;
|
material->shader = shader;
|
||||||
material->diffuse_map = ResourceCache::load_texture(texture_path);
|
material->diffuse_map = ResourceCache::load_texture(diffuse_path);
|
||||||
|
|
||||||
|
// Optional, like in the OBJ loader: without it specular_color is used alone
|
||||||
|
if (!specular_path.empty()) {
|
||||||
|
material->specular_map = ResourceCache::load_texture(specular_path, false);
|
||||||
|
}
|
||||||
|
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,11 +550,21 @@ void draw_panel_window(AppState& app)
|
|||||||
ImGui::SeparatorText("Scene Selector");
|
ImGui::SeparatorText("Scene Selector");
|
||||||
|
|
||||||
for (size_t i = 0; i < app.scenes.size(); ++i) {
|
for (size_t i = 0; i < app.scenes.size(); ++i) {
|
||||||
|
const std::string& name = app.scenes[i]->name;
|
||||||
|
|
||||||
char label[64];
|
char label[64];
|
||||||
|
if (name.empty()) {
|
||||||
ImFormatString(label, IM_ARRAYSIZE(label), "Scene %zu", i);
|
ImFormatString(label, IM_ARRAYSIZE(label), "Scene %zu", i);
|
||||||
|
} else {
|
||||||
|
ImFormatString(label, IM_ARRAYSIZE(label), "%s", name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImGui identifies widgets by label, the index keeps equal names apart
|
||||||
|
ImGui::PushID(static_cast<int>(i));
|
||||||
if (ImGui::RadioButton(label, app.selected_scene_index == i)) {
|
if (ImGui::RadioButton(label, app.selected_scene_index == i)) {
|
||||||
app.selected_scene_index = i;
|
app.selected_scene_index = i;
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SeparatorText("Camera Settings");
|
ImGui::SeparatorText("Camera Settings");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef FAN_SCENE_HPP_
|
#ifndef FAN_SCENE_HPP_
|
||||||
#define FAN_SCENE_HPP_
|
#define FAN_SCENE_HPP_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "entity.hpp"
|
#include "entity.hpp"
|
||||||
@@ -12,6 +13,7 @@ namespace Fan
|
|||||||
class Scene
|
class Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
std::string name{};
|
||||||
LightEnvironment light_environment{};
|
LightEnvironment light_environment{};
|
||||||
|
|
||||||
// Stores a copy: later changes to the passed Entity don't affect the scene.
|
// Stores a copy: later changes to the passed Entity don't affect the scene.
|
||||||
|
|||||||
Reference in New Issue
Block a user