2D scene rendering + image loading #15
@@ -0,0 +1,7 @@
|
||||
add_executable(image_viewer main.cpp)
|
||||
|
||||
target_link_libraries(image_viewer PRIVATE ${PROJECT_NAME})
|
||||
|
||||
target_compile_definitions(image_viewer PRIVATE
|
||||
IMAGE_VIEWER_ASSET_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
@@ -0,0 +1,79 @@
|
||||
#include <imgui.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sophia/application.hpp>
|
||||
#include <sophia/components.hpp>
|
||||
#include <sophia/entity.hpp>
|
||||
#include <sophia/scene_view.hpp>
|
||||
#include <sophia/ui/panel.hpp>
|
||||
#include <string>
|
||||
|
||||
// Shows a render target filling the whole panel.
|
||||
class ViewportPanel : public sophia::Panel {
|
||||
public:
|
||||
ViewportPanel(sophia::UI& ui, sophia::RenderTargetHandle target)
|
||||
: Panel{{.name = "Image",
|
||||
.windowFlags = ImGuiWindowFlags_NoScrollbar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse}},
|
||||
ui{ui},
|
||||
target{target} {}
|
||||
|
||||
void onUpdate(const sophia::FrameInfo&) override { ui.image(target); }
|
||||
|
||||
private:
|
||||
sophia::UI& ui;
|
||||
sophia::RenderTargetHandle target;
|
||||
};
|
||||
|
||||
// Displays an image file (anything stb_image reads: JPEG, PNG, BMP, ...) as a
|
||||
// sprite in a 2D scene, scaled to fit the viewport.
|
||||
// image_viewer [path]
|
||||
class ImageViewer : public sophia::Application {
|
||||
public:
|
||||
ImageViewer()
|
||||
: Application{{.width = 1000, .height = 750, .name = "ImageViewer"}} {}
|
||||
|
||||
void onCreate() override {
|
||||
std::string path =
|
||||
args.size() > 1 ? args[1] : IMAGE_VIEWER_ASSET_DIR "/dog.jpeg";
|
||||
|
||||
sophia::SceneHandle sceneHandle = scenes().create();
|
||||
sophia::Scene& scene = scenes().get(sceneHandle);
|
||||
|
||||
camera = scene.createEntity("Camera");
|
||||
camera.addComponent<sophia::CameraComponent>();
|
||||
|
||||
sophia::TextureHandle texture = resources().load<sophia::Texture>(path);
|
||||
imageSize = resources().getExtent(texture);
|
||||
|
||||
// One world unit per image pixel; the camera zooms to fit.
|
||||
sophia::Entity image = scene.createEntity("Image");
|
||||
image.addComponent<sophia::SpriteComponent>(
|
||||
sophia::SpriteComponent{.texture = texture, .size = imageSize});
|
||||
|
||||
target = resources().create<sophia::RenderTarget>();
|
||||
views().create({.scene = sceneHandle,
|
||||
.target = target,
|
||||
.camera = camera,
|
||||
.clearColor = {0.1f, 0.1f, 0.15f, 1.f}});
|
||||
|
||||
panels().emplace<ViewportPanel>(ui(), target);
|
||||
// panels().setDefaultLayout({.center = {"Image"}});
|
||||
}
|
||||
|
||||
void onUpdate(const sophia::FrameInfo&) override {
|
||||
// Fit the whole image: show enough height that neither dimension of the
|
||||
// image overflows the viewport.
|
||||
glm::vec2 viewport = resources().getExtent(target);
|
||||
float viewportAspect = viewport.x / viewport.y;
|
||||
camera.getComponent<sophia::CameraComponent>().ortho.height =
|
||||
std::max(imageSize.y, imageSize.x / viewportAspect);
|
||||
}
|
||||
|
||||
private:
|
||||
sophia::Entity camera;
|
||||
sophia::RenderTargetHandle target{};
|
||||
glm::vec2 imageSize{1.f};
|
||||
};
|
||||
|
||||
SOPHIA_MAIN(ImageViewer)
|
||||
Reference in New Issue
Block a user