diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cd972bd9..e9e696730 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(GUACAMOLE CXX) # version number set(GUACAMOLE_MAJOR 0) set(GUACAMOLE_MINOR 7) -set(GUACAMOLE_PATCH 0) +set(GUACAMOLE_PATCH 1) set(GUACAMOLE_VERSION ${GUACAMOLE_MAJOR}.${GUACAMOLE_MINOR}.${GUACAMOLE_PATCH}) set(GUACAMOLE_DESCRIPTION "GUACAMOLE - an astonishing virtual reality engine") set(GUACAMOLE_HOMEPAGE "http://www.GUACAMOLE.org") diff --git a/include/gua/renderer/CompositePass.hpp b/include/gua/renderer/CompositePass.hpp index 607518f9b..37793495c 100644 --- a/include/gua/renderer/CompositePass.hpp +++ b/include/gua/renderer/CompositePass.hpp @@ -1,88 +1,89 @@ -/****************************************************************************** - * guacamole - delicious VR * - * * - * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * - * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * - * * - * This program is free software: you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the Free * - * Software Foundation, either version 3 of the License, or (at your option) * - * any later version. * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General Public License along * - * with this program. If not, see . * - * * - ******************************************************************************/ - -#ifndef GUA_COMPOSITE_PASS_HPP -#define GUA_COMPOSITE_PASS_HPP - -// guacamole headers -#include -#include -#include - -namespace gua { - -class GBuffer; - -/** - * - */ -class CompositePass : public Pass { - public: - - /** - * - */ - CompositePass(Pipeline* pipeline); - - /** - * - */ - virtual ~CompositePass(); - - virtual void create(RenderContext const& ctx, - std::vector > const& layers); - - /* virtual */ LayerMapping const* get_gbuffer_mapping() const; - - void print_shaders(std::string const& directory, - std::string const& name) const; - - bool pre_compile_shaders(RenderContext const& ctx); - - /* virtual */ void render_scene(Camera const& camera, - SceneGraph const&, - RenderContext const& ctx); - -protected : - - /* virtual */ void rendering( SerializedScene const& scene, - RenderContext const& ctx, - CameraMode eye, - Camera const& camera, - FrameBufferObject* target); - - void init_resources (RenderContext const& ctx); - - private: - - GBuffer* volume_raygeneration_buffer_; - - scm::gl::depth_stencil_state_ptr depth_stencil_state_; - scm::gl::quad_geometry_ptr fullscreen_quad_; - - ShaderProgram* composite_shader_; - ShaderProgram* ray_generation_shader_; -}; - -} - -#endif // GUA_COMPOSITE_PASS_HPP +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_COMPOSITE_PASS_HPP +#define GUA_COMPOSITE_PASS_HPP + +// guacamole headers +#include +#include +#include + +namespace gua { + +class GBuffer; + +/** + * + */ +class CompositePass : public Pass { + public: + + /** + * + */ + CompositePass(Pipeline* pipeline); + + /** + * + */ + virtual ~CompositePass(); + + virtual void create(RenderContext const& ctx, + std::vector > const& layers); + + /* virtual */ LayerMapping const* get_gbuffer_mapping() const; + + void print_shaders(std::string const& directory, + std::string const& name) const; + + bool pre_compile_shaders(RenderContext const& ctx); + + /* virtual */ void render_scene(Camera const& camera, + SceneGraph const&, + RenderContext const& ctx, + std::size_t viewid); + +protected : + + /* virtual */ void rendering( SerializedScene const& scene, + RenderContext const& ctx, + CameraMode eye, + Camera const& camera, + FrameBufferObject* target); + + void init_resources (RenderContext const& ctx); + + private: + + GBuffer* volume_raygeneration_buffer_; + + scm::gl::depth_stencil_state_ptr depth_stencil_state_; + scm::gl::quad_geometry_ptr fullscreen_quad_; + + ShaderProgram* composite_shader_; + ShaderProgram* ray_generation_shader_; +}; + +} + +#endif // GUA_COMPOSITE_PASS_HPP diff --git a/include/gua/renderer/FullscreenPass.hpp b/include/gua/renderer/FullscreenPass.hpp index 9a445e35a..d74c13ce3 100644 --- a/include/gua/renderer/FullscreenPass.hpp +++ b/include/gua/renderer/FullscreenPass.hpp @@ -1,109 +1,109 @@ -/****************************************************************************** - * guacamole - delicious VR * - * * - * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * - * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * - * * - * This program is free software: you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the Free * - * Software Foundation, either version 3 of the License, or (at your option) * - * any later version. * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General Public License along * - * with this program. If not, see . * - * * - ******************************************************************************/ - -#ifndef GUA_FULLSCREEN_PASS_HPP -#define GUA_FULLSCREEN_PASS_HPP - -// guacamole headers -#include - -// external headers -#include -#include - -namespace gua { - -class ShaderProgram; -class SceneGraph; - -/** - * A GeometryPass which automatically renders to a fullscreen quad. - * - * This is especially useful for deferred shading or other post - * processing purposes. - * - * Render passes are part of a rendering pipeline. Basically they encapsulate - * some FBOs to which the scene is rendered. The user has to add some color - * buffers to this pass and a depth stencil buffer if desired. The scene is - * rendered frome the point of view of a given camera through a given screen. - * With render masks a part of the scene may be hidden. - */ -class FullscreenPass : public Pass { - public: - - /** - * - */ - FullscreenPass(Pipeline* pipeline); - - /** - * Destructor. - * - * Deletes the FullscreenPass and frees all associated data. - */ - virtual ~FullscreenPass(); - - /** - * - */ - void render_scene(Camera const& camera, SceneGraph const&, RenderContext const& ctx); - - protected: - - /** - * - */ - virtual void set_uniforms(SerializedScene const& scene, - RenderContext const& ctx) {} - - /** - * - */ - virtual void pre_rendering(Camera const& camera, - SerializedScene const& scene, - CameraMode eye, - RenderContext const& ctx) {} - - /** - * - */ - virtual void rendering(Camera const& camera, - SerializedScene const& scene, - CameraMode eye, - RenderContext const& ctx) = 0; - - /** - * - */ - virtual void post_rendering(Camera const& camera, - SerializedScene const& scene, - CameraMode eye, - RenderContext const& ctx) {} - - scm::gl::quad_geometry_ptr fullscreen_quad_; - scm::gl::depth_stencil_state_ptr depth_stencil_state_; - - private: -}; - -} - -#endif // GUA_FULLSCREEN_PASS_HPP +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_FULLSCREEN_PASS_HPP +#define GUA_FULLSCREEN_PASS_HPP + +// guacamole headers +#include + +// external headers +#include +#include + +namespace gua { + +class ShaderProgram; +class SceneGraph; + +/** + * A GeometryPass which automatically renders to a fullscreen quad. + * + * This is especially useful for deferred shading or other post + * processing purposes. + * + * Render passes are part of a rendering pipeline. Basically they encapsulate + * some FBOs to which the scene is rendered. The user has to add some color + * buffers to this pass and a depth stencil buffer if desired. The scene is + * rendered frome the point of view of a given camera through a given screen. + * With render masks a part of the scene may be hidden. + */ +class FullscreenPass : public Pass { + public: + + /** + * + */ + FullscreenPass(Pipeline* pipeline); + + /** + * Destructor. + * + * Deletes the FullscreenPass and frees all associated data. + */ + virtual ~FullscreenPass(); + + /** + * + */ + void render_scene(Camera const& camera, SceneGraph const&, RenderContext const& ctx, std::size_t viewid); + + protected: + + /** + * + */ + virtual void set_uniforms(SerializedScene const& scene, + RenderContext const& ctx) {} + + /** + * + */ + virtual void pre_rendering(Camera const& camera, + SerializedScene const& scene, + CameraMode eye, + RenderContext const& ctx) {} + + /** + * + */ + virtual void rendering(Camera const& camera, + SerializedScene const& scene, + CameraMode eye, + RenderContext const& ctx) = 0; + + /** + * + */ + virtual void post_rendering(Camera const& camera, + SerializedScene const& scene, + CameraMode eye, + RenderContext const& ctx) {} + + scm::gl::quad_geometry_ptr fullscreen_quad_; + scm::gl::depth_stencil_state_ptr depth_stencil_state_; + + private: +}; + +} + +#endif // GUA_FULLSCREEN_PASS_HPP diff --git a/include/gua/renderer/GBufferPass.hpp b/include/gua/renderer/GBufferPass.hpp index 118e3f08e..bcaf5b481 100644 --- a/include/gua/renderer/GBufferPass.hpp +++ b/include/gua/renderer/GBufferPass.hpp @@ -74,15 +74,19 @@ class GBufferPass : public GeometryPass { RenderContext const& ctx, CameraMode eye, Camera const& camera, - FrameBufferObject* target); + FrameBufferObject* target, + std::size_t viewid); void display_bboxes(RenderContext const& ctx, - SerializedScene const& scene); + SerializedScene const& scene, + std::size_t viewid); void display_rays (RenderContext const& ctx, - SerializedScene const& scene); + SerializedScene const& scene, + std::size_t viewid); void display_quads (RenderContext const& ctx, SerializedScene const& scene, - CameraMode eye); + CameraMode eye, + std::size_t viewid); void update_ubershader_from_scene(SerializedScene const& scene, SceneGraph const& graph); diff --git a/include/gua/renderer/GeometryPass.hpp b/include/gua/renderer/GeometryPass.hpp index 990e5d31b..07c4cccf6 100644 --- a/include/gua/renderer/GeometryPass.hpp +++ b/include/gua/renderer/GeometryPass.hpp @@ -58,7 +58,8 @@ class GeometryPass : public Pass { virtual void render_scene(Camera const& camera, SceneGraph const& current_graph, - RenderContext const& ctx); + RenderContext const& ctx, + std::size_t viewid); protected: virtual void rendering(SerializedScene const& scene, @@ -66,7 +67,8 @@ class GeometryPass : public Pass { RenderContext const& ctx, CameraMode eye, Camera const& camera, - FrameBufferObject* target) = 0; + FrameBufferObject* target, + std::size_t viewid) = 0; private: }; diff --git a/include/gua/renderer/GeometryUberShader.hpp b/include/gua/renderer/GeometryUberShader.hpp index 6c203486e..ebbde7c05 100644 --- a/include/gua/renderer/GeometryUberShader.hpp +++ b/include/gua/renderer/GeometryUberShader.hpp @@ -85,7 +85,8 @@ class GeometryUberShader : public UberShader { std::string const& material, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& frustum) const = 0; + Frustum const& frustum, + std::size_t viewid ) const = 0; /** * This method is called for ONCE per drawable to perform draw operations @@ -97,7 +98,8 @@ class GeometryUberShader : public UberShader { std::string const& material, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& frustum) const = 0; + Frustum const& frustum, + std::size_t viewid) const = 0; /** * This method is called for ONCE per drawable to perform postdraw operations @@ -109,7 +111,8 @@ class GeometryUberShader : public UberShader { std::string const& material, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& frustum) const = 0; + Frustum const& frustum, + std::size_t viewid) const = 0; /** * This callback is called ONCE per frame AFTER rendering all drawables of this type diff --git a/include/gua/renderer/LightingPass.hpp b/include/gua/renderer/LightingPass.hpp index bcfb2748e..70ce747bc 100644 --- a/include/gua/renderer/LightingPass.hpp +++ b/include/gua/renderer/LightingPass.hpp @@ -74,7 +74,8 @@ class LightingPass : public GeometryPass { RenderContext const& ctx, CameraMode eye, Camera const& camera, - FrameBufferObject* target); + FrameBufferObject* target, + std::size_t viewid); void init_resources(RenderContext const& ctx); diff --git a/include/gua/renderer/NURBSUberShader.hpp b/include/gua/renderer/NURBSUberShader.hpp index dc2f5d32a..b426c1c4e 100644 --- a/include/gua/renderer/NURBSUberShader.hpp +++ b/include/gua/renderer/NURBSUberShader.hpp @@ -52,21 +52,24 @@ class NURBSUberShader : public GeometryUberShader { std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const; + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const; /*virtual*/ void draw (RenderContext const& ctx, std::string const& ksfile_name, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const; + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const; /*virtual*/ void postdraw (RenderContext const& ctx, std::string const& ksfile_name, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const; + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const; /*virtual*/ void postframe(RenderContext const& ctx) const; diff --git a/include/gua/renderer/Pass.hpp b/include/gua/renderer/Pass.hpp index 7d6315107..faee2ca3f 100644 --- a/include/gua/renderer/Pass.hpp +++ b/include/gua/renderer/Pass.hpp @@ -66,7 +66,8 @@ class Pass { virtual void render_scene(Camera const& camera, SceneGraph const& current_graph, - RenderContext const& ctx) = 0; + RenderContext const& ctx, + std::size_t unique_view_id) = 0; // not strictly necessary to call, but recommend // to avoid crashes on shader compilation diff --git a/include/gua/renderer/Pipeline.hpp b/include/gua/renderer/Pipeline.hpp index 104476015..9c9ac45d2 100644 --- a/include/gua/renderer/Pipeline.hpp +++ b/include/gua/renderer/Pipeline.hpp @@ -185,6 +185,10 @@ class GUA_DLL Pipeline { SerializedScene const& get_current_scene(CameraMode mode) const; + inline std::size_t uuid() const { + return reinterpret_cast(this); + } + friend class Renderer; private: diff --git a/include/gua/renderer/PostFXPass.hpp b/include/gua/renderer/PostFXPass.hpp index 0cb40f30f..e36d1a599 100644 --- a/include/gua/renderer/PostFXPass.hpp +++ b/include/gua/renderer/PostFXPass.hpp @@ -56,7 +56,7 @@ class PostFXPass : public Pass { virtual void cleanup(RenderContext const& ctx); - void render_scene(Camera const& camera, SceneGraph const&, RenderContext const& ctx); + void render_scene(Camera const& camera, SceneGraph const&, RenderContext const& ctx, std::size_t viewid); /* virtual */ LayerMapping const* get_gbuffer_mapping() const; diff --git a/include/gua/renderer/ShadowMap.hpp b/include/gua/renderer/ShadowMap.hpp index 846ca260d..2b5238e15 100644 --- a/include/gua/renderer/ShadowMap.hpp +++ b/include/gua/renderer/ShadowMap.hpp @@ -82,6 +82,8 @@ class ShadowMap { virtual void cleanup(RenderContext const& context); + inline std::size_t const uuid() const { return reinterpret_cast(buffer_); } + private: void update_members(RenderContext const& ctx, unsigned map_size); diff --git a/include/gua/renderer/TriMeshUberShader.hpp b/include/gua/renderer/TriMeshUberShader.hpp index 935cf2cd7..bed35daec 100644 --- a/include/gua/renderer/TriMeshUberShader.hpp +++ b/include/gua/renderer/TriMeshUberShader.hpp @@ -42,21 +42,24 @@ class TriMeshUberShader : public GeometryUberShader { std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const; + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const; /*virtual*/ void draw (RenderContext const& ctx, std::string const& filename, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const; + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const; /*virtual*/ void postdraw (RenderContext const& ctx, std::string const& filename, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const; + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const; /*virtual*/ void postframe (RenderContext const& context) const; }; diff --git a/include/gua/renderer/Video3DUberShader.hpp b/include/gua/renderer/Video3DUberShader.hpp index 688e67bdb..8b7d193fb 100644 --- a/include/gua/renderer/Video3DUberShader.hpp +++ b/include/gua/renderer/Video3DUberShader.hpp @@ -58,21 +58,24 @@ class GUA_DLL Video3DUberShader : public GeometryUberShader { std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& frustum) const; + Frustum const& frustum, + std::size_t viewid) const; /*virtual*/ void draw (RenderContext const& context, std::string const& ksfile_name, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& frustum) const; + Frustum const& frustum, + std::size_t viewid) const; /*virtual*/ void postdraw(RenderContext const& context, std::string const& ksfile_name, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& frustum) const; + Frustum const& frustum, + std::size_t viewid) const; /*virtual*/ void postframe(RenderContext const& context) const; @@ -100,6 +103,7 @@ class GUA_DLL Video3DUberShader : public GeometryUberShader { mutable std::vector warp_color_result_; mutable std::vector warp_result_fbo_; + mutable std::vector no_bfc_rasterizer_state_; mutable std::vector nearest_sampler_state_; mutable std::vector linear_sampler_state_; diff --git a/include/gua/scenegraph/GeometryNode.hpp b/include/gua/scenegraph/GeometryNode.hpp index b4c0dc9c7..8812c7aa1 100644 --- a/include/gua/scenegraph/GeometryNode.hpp +++ b/include/gua/scenegraph/GeometryNode.hpp @@ -99,6 +99,8 @@ class GUA_DLL GeometryNode : public Node { */ virtual void update_bounding_box() const; + inline virtual void update_cache() { Node::update_cache(); } + /** * Accepts a visitor and calls concrete visit method. * @@ -112,13 +114,12 @@ class GUA_DLL GeometryNode : public Node { virtual std::shared_ptr copy() const = 0; - virtual void cache_material() const; - std::string filename_; std::string material_; ShadowMode shadow_mode_; - bool filename_changed_; bool material_changed_; + bool filename_changed_; + bool material_changed_; }; } diff --git a/include/gua/scenegraph/NURBSNode.hpp b/include/gua/scenegraph/NURBSNode.hpp index a1c14c591..4f9f67e35 100644 --- a/include/gua/scenegraph/NURBSNode.hpp +++ b/include/gua/scenegraph/NURBSNode.hpp @@ -48,9 +48,12 @@ public : // member PickResult::Options options, Mask const& mask, std::set& hits); + + /* virtual */ void update_cache(); + protected: - /*virtual*/ std::shared_ptr copy() const; + /* virtual */ std::shared_ptr copy() const; private : // attributes e.g. special attributes for drawing diff --git a/include/gua/scenegraph/Video3DNode.hpp b/include/gua/scenegraph/Video3DNode.hpp index add44393d..67367c968 100644 --- a/include/gua/scenegraph/Video3DNode.hpp +++ b/include/gua/scenegraph/Video3DNode.hpp @@ -51,6 +51,8 @@ class GUA_DLL Video3DNode : public GeometryNode { Mask const& mask, std::set& hits); + /* virtual */ void update_cache(); + protected: /*virtual*/ std::shared_ptr copy() const; diff --git a/src/gua/databases/MaterialDatabase.cpp b/src/gua/databases/MaterialDatabase.cpp index b282d357d..74922f4d8 100644 --- a/src/gua/databases/MaterialDatabase.cpp +++ b/src/gua/databases/MaterialDatabase.cpp @@ -54,10 +54,7 @@ void MaterialDatabase::load_material(std::string const& filename) { if (!instance()->is_supported(filename)) { auto mat = std::make_shared(filename, filename); instance()->add(filename, mat); - std::cout << "MaterialDatabase::load_material() : loading " << filename << std::endl; - } - else { - std::cout << "MaterialDatabase::load_material() : material not supported " << filename << std::endl; + Logger::LOG_MESSAGE << "MaterialDatabase::load_material() : loading " << filename << std::endl; } } diff --git a/src/gua/renderer/CompositePass.cpp b/src/gua/renderer/CompositePass.cpp index fc756966e..52047496b 100644 --- a/src/gua/renderer/CompositePass.cpp +++ b/src/gua/renderer/CompositePass.cpp @@ -1,281 +1,282 @@ -/****************************************************************************** - * guacamole - delicious VR * - * * - * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * - * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * - * * - * This program is free software: you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the Free * - * Software Foundation, either version 3 of the License, or (at your option) * - * any later version. * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General Public License along * - * with this program. If not, see . * - * * - ******************************************************************************/ - -// class header -#include - -// guacamole headers -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace gua { - -//////////////////////////////////////////////////////////////////////////////// - -CompositePass::CompositePass(Pipeline* pipeline) : - Pass(pipeline), - composite_shader_(new ShaderProgram), - ray_generation_shader_(new ShaderProgram), - volume_raygeneration_buffer_(nullptr) -{ - std::string vertex_shader (Resources::lookup_shader(Resources::shaders_uber_shaders_composite_compose_vert)); - std::string fragment_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_compose_frag)); - - composite_shader_->create_from_sources(vertex_shader, fragment_shader); - - std::string ray_generation_vertex_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_ray_generation_vert)); - std::string ray_generation_fragment_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_ray_generation_frag)); - - ray_generation_shader_->create_from_sources(ray_generation_vertex_shader, ray_generation_fragment_shader); -} - -//////////////////////////////////////////////////////////////////////////////// - -CompositePass::~CompositePass() { - - if (composite_shader_) { - delete composite_shader_; - } - - if (volume_raygeneration_buffer_) { - delete volume_raygeneration_buffer_; - } - - if (ray_generation_shader_) { - delete ray_generation_shader_; - } -} - -//////////////////////////////////////////////////////////////////////////////// - -void CompositePass::create(RenderContext const& ctx, std::vector> const& layers) { - - // reuse gbuffer from shading-pass - gbuffer_ = inputs_[Pipeline::PipelineStage::shading]; - /*scm::gl::sampler_state_desc tmp(scm::gl::FILTER_MIN_MAG_LINEAR, - scm::gl::WRAP_CLAMP_TO_EDGE, - scm::gl::WRAP_CLAMP_TO_EDGE); - Pass::create(ctx, config, { { BufferComponent::F3, tmp } });*/ - - - if (volume_raygeneration_buffer_) { - volume_raygeneration_buffer_->remove_buffers(ctx); - delete volume_raygeneration_buffer_; - } - - scm::gl::sampler_state_desc state(scm::gl::FILTER_MIN_MAG_LINEAR, - scm::gl::WRAP_CLAMP_TO_EDGE, - scm::gl::WRAP_CLAMP_TO_EDGE); - - std::vector> layer_3f_desc; - layer_3f_desc.push_back(std::make_pair(BufferComponent::F3, state)); - - volume_raygeneration_buffer_ = new GBuffer(layer_3f_desc, - pipeline_->config.get_left_resolution()[0], - pipeline_->config.get_left_resolution()[1]); - volume_raygeneration_buffer_->create(ctx); -} - -//////////////////////////////////////////////////////////////////////////////// - -/* virtual */ void CompositePass::rendering(SerializedScene const& scene, - RenderContext const& ctx, - CameraMode eye, - Camera const& camera, - FrameBufferObject* target) -{ - init_resources(ctx); - - ctx.render_context->set_depth_stencil_state(depth_stencil_state_); - - // 1. render proxy geometry into fbo - volume_raygeneration_buffer_->bind(ctx); - { - scm::math::vec2f resolution(volume_raygeneration_buffer_->width(), volume_raygeneration_buffer_->height()); - ctx.render_context->set_viewport(scm::gl::viewport(math::vec2(0, 0), resolution)); - - volume_raygeneration_buffer_->clear_color_buffers(ctx, gua::utils::Color3f(0.0f, 0.0f, 0.0f)); - volume_raygeneration_buffer_->clear_depth_stencil_buffer(ctx); - - ///TODO: Toplevel - if (!scene.volumenodes_.empty()) - { - // gather input textures and set uniforms - Pass::set_camera_matrices(*ray_generation_shader_, camera, pipeline_->get_current_scene(eye), eye, ctx); - - ray_generation_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->width(), "gua_texel_width"); - ray_generation_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->height(), "gua_texel_height"); - - - volume_raygeneration_buffer_->clear_color_buffers(ctx, gua::utils::Color3f(0.0f, 0.0f, 0.0f)); - volume_raygeneration_buffer_->clear_depth_stencil_buffer(ctx); - - for (auto const& node : scene.volumenodes_) { - - auto volume = - std::static_pointer_cast(GeometryDatabase::instance()->lookup(node->data.get_volume())); - - if (volume) { - ray_generation_shader_->set_uniform( - ctx, node->get_world_transform(), "gua_model_matrix"); - - ray_generation_shader_->set_uniform( - ctx, 0, "volume_frag_id"); - - ray_generation_shader_->use(ctx); - { - volume->draw_proxy(ctx); - } - ray_generation_shader_->unuse(ctx); - } - } - } - } - volume_raygeneration_buffer_->unbind(ctx); - - scm::gl::context_all_guard cug(ctx.render_context); - - // 2. render fullscreen quad for compositing and volume ray castinG - Pass::set_camera_matrices(*composite_shader_, camera, pipeline_->get_current_scene(eye), eye, ctx); - - auto input_tex(inputs_[Pipeline::shading]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); - auto normal_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); - auto depth_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_depth_buffer()); - - auto raygen_tex(volume_raygeneration_buffer_->get_color_buffers(TYPE_FLOAT)[0]); - - composite_shader_->set_uniform(ctx, input_tex, "gua_color_gbuffer_in"); - composite_shader_->set_uniform(ctx, normal_tex, "gua_normal_gbuffer_in"); - composite_shader_->set_uniform(ctx, depth_tex, "gua_depth_gbuffer_in"); - composite_shader_->set_uniform(ctx, raygen_tex, "gua_ray_entry_in"); - - composite_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->width(), "gua_texel_width"); - composite_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->height(), "gua_texel_height"); - - // bind target fbo and set viewport - target->bind(ctx); - ctx.render_context->set_viewport(scm::gl::viewport( - math::vec2(0, 0), - ::scm::math::vec2f(target->width(), target->height()))); - - if (!scene.volumenodes_.empty()){ - - for (auto const& node : scene.volumenodes_) { - - auto volume = - std::static_pointer_cast(GeometryDatabase::instance()->lookup(node->data.get_volume())); - - if (volume) { - composite_shader_->set_uniform( - ctx, node->get_world_transform(), "gua_model_matrix"); - - volume->set_uniforms(ctx, composite_shader_); - - composite_shader_->use(ctx); - { - fullscreen_quad_->draw(ctx.render_context); - } - composite_shader_->unuse(ctx); - } - } - - } - - target->unbind(ctx); - - ctx.render_context->reset_state_objects(); -} - -//////////////////////////////////////////////////////////////////////////////// - -void CompositePass::init_resources(RenderContext const& ctx) { - if (!initialized_) { - if (!depth_stencil_state_) { - depth_stencil_state_ = ctx.render_device->create_depth_stencil_state(false, false, scm::gl::COMPARISON_NEVER); - } - - if (!fullscreen_quad_) { - fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry(ctx.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); - } - initialized_ = true; - } -} - -//////////////////////////////////////////////////////////////////////////////// - -/* virtual */ LayerMapping const* CompositePass::get_gbuffer_mapping() const { - throw std::runtime_error("no gbuffer mapping available for composite pass"); -} - -//////////////////////////////////////////////////////////////////////////////// - -void CompositePass::print_shaders(std::string const& directory, - std::string const& name) const { - composite_shader_->save_to_file(directory, name + "/composite_shader"); - ray_generation_shader_->save_to_file(directory, name + "/ray_generation_shader"); -} - -//////////////////////////////////////////////////////////////////////////////// - -bool CompositePass::pre_compile_shaders(RenderContext const& ctx) { - - if (composite_shader_) return composite_shader_->upload_to(ctx); - if (ray_generation_shader_) return ray_generation_shader_->upload_to(ctx); - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// - -void CompositePass::render_scene(Camera const& camera, - SceneGraph const&, - RenderContext const& ctx) { - - for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { - - FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); - - CameraMode eye(CameraMode::CENTER); - if (gbuffer_->get_eye_buffers().size() > 1 && i == 0) - eye = CameraMode::LEFT; - if (gbuffer_->get_eye_buffers().size() > 1 && i == 1) - eye = CameraMode::RIGHT; - - fbo->bind(ctx); - - ctx.render_context->set_viewport(scm::gl::viewport( - math::vec2(0, 0), ::scm::math::vec2f(fbo->width(), fbo->height()))); - - rendering(pipeline_->get_current_scene(eye), ctx, eye, camera, fbo); - - fbo->unbind(ctx); - } -} - -} +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace gua { + +//////////////////////////////////////////////////////////////////////////////// + +CompositePass::CompositePass(Pipeline* pipeline) : + Pass(pipeline), + composite_shader_(new ShaderProgram), + ray_generation_shader_(new ShaderProgram), + volume_raygeneration_buffer_(nullptr) +{ + std::string vertex_shader (Resources::lookup_shader(Resources::shaders_uber_shaders_composite_compose_vert)); + std::string fragment_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_compose_frag)); + + composite_shader_->create_from_sources(vertex_shader, fragment_shader); + + std::string ray_generation_vertex_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_ray_generation_vert)); + std::string ray_generation_fragment_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_ray_generation_frag)); + + ray_generation_shader_->create_from_sources(ray_generation_vertex_shader, ray_generation_fragment_shader); +} + +//////////////////////////////////////////////////////////////////////////////// + +CompositePass::~CompositePass() { + + if (composite_shader_) { + delete composite_shader_; + } + + if (volume_raygeneration_buffer_) { + delete volume_raygeneration_buffer_; + } + + if (ray_generation_shader_) { + delete ray_generation_shader_; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::create(RenderContext const& ctx, std::vector> const& layers) { + + // reuse gbuffer from shading-pass + gbuffer_ = inputs_[Pipeline::PipelineStage::shading]; + /*scm::gl::sampler_state_desc tmp(scm::gl::FILTER_MIN_MAG_LINEAR, + scm::gl::WRAP_CLAMP_TO_EDGE, + scm::gl::WRAP_CLAMP_TO_EDGE); + Pass::create(ctx, config, { { BufferComponent::F3, tmp } });*/ + + + if (volume_raygeneration_buffer_) { + volume_raygeneration_buffer_->remove_buffers(ctx); + delete volume_raygeneration_buffer_; + } + + scm::gl::sampler_state_desc state(scm::gl::FILTER_MIN_MAG_LINEAR, + scm::gl::WRAP_CLAMP_TO_EDGE, + scm::gl::WRAP_CLAMP_TO_EDGE); + + std::vector> layer_3f_desc; + layer_3f_desc.push_back(std::make_pair(BufferComponent::F3, state)); + + volume_raygeneration_buffer_ = new GBuffer(layer_3f_desc, + pipeline_->config.get_left_resolution()[0], + pipeline_->config.get_left_resolution()[1]); + volume_raygeneration_buffer_->create(ctx); +} + +//////////////////////////////////////////////////////////////////////////////// + +/* virtual */ void CompositePass::rendering(SerializedScene const& scene, + RenderContext const& ctx, + CameraMode eye, + Camera const& camera, + FrameBufferObject* target) +{ + init_resources(ctx); + + ctx.render_context->set_depth_stencil_state(depth_stencil_state_); + + // 1. render proxy geometry into fbo + volume_raygeneration_buffer_->bind(ctx); + { + scm::math::vec2f resolution(volume_raygeneration_buffer_->width(), volume_raygeneration_buffer_->height()); + ctx.render_context->set_viewport(scm::gl::viewport(math::vec2(0, 0), resolution)); + + volume_raygeneration_buffer_->clear_color_buffers(ctx, gua::utils::Color3f(0.0f, 0.0f, 0.0f)); + volume_raygeneration_buffer_->clear_depth_stencil_buffer(ctx); + + ///TODO: Toplevel + if (!scene.volumenodes_.empty()) + { + // gather input textures and set uniforms + Pass::set_camera_matrices(*ray_generation_shader_, camera, pipeline_->get_current_scene(eye), eye, ctx); + + ray_generation_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->width(), "gua_texel_width"); + ray_generation_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->height(), "gua_texel_height"); + + + volume_raygeneration_buffer_->clear_color_buffers(ctx, gua::utils::Color3f(0.0f, 0.0f, 0.0f)); + volume_raygeneration_buffer_->clear_depth_stencil_buffer(ctx); + + for (auto const& node : scene.volumenodes_) { + + auto volume = + std::static_pointer_cast(GeometryDatabase::instance()->lookup(node->data.get_volume())); + + if (volume) { + ray_generation_shader_->set_uniform( + ctx, node->get_world_transform(), "gua_model_matrix"); + + ray_generation_shader_->set_uniform( + ctx, 0, "volume_frag_id"); + + ray_generation_shader_->use(ctx); + { + volume->draw_proxy(ctx); + } + ray_generation_shader_->unuse(ctx); + } + } + } + } + volume_raygeneration_buffer_->unbind(ctx); + + scm::gl::context_all_guard cug(ctx.render_context); + + // 2. render fullscreen quad for compositing and volume ray castinG + Pass::set_camera_matrices(*composite_shader_, camera, pipeline_->get_current_scene(eye), eye, ctx); + + auto input_tex(inputs_[Pipeline::shading]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); + auto normal_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); + auto depth_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_depth_buffer()); + + auto raygen_tex(volume_raygeneration_buffer_->get_color_buffers(TYPE_FLOAT)[0]); + + composite_shader_->set_uniform(ctx, input_tex, "gua_color_gbuffer_in"); + composite_shader_->set_uniform(ctx, normal_tex, "gua_normal_gbuffer_in"); + composite_shader_->set_uniform(ctx, depth_tex, "gua_depth_gbuffer_in"); + composite_shader_->set_uniform(ctx, raygen_tex, "gua_ray_entry_in"); + + composite_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->width(), "gua_texel_width"); + composite_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->height(), "gua_texel_height"); + + // bind target fbo and set viewport + target->bind(ctx); + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), + ::scm::math::vec2f(target->width(), target->height()))); + + if (!scene.volumenodes_.empty()){ + + for (auto const& node : scene.volumenodes_) { + + auto volume = + std::static_pointer_cast(GeometryDatabase::instance()->lookup(node->data.get_volume())); + + if (volume) { + composite_shader_->set_uniform( + ctx, node->get_world_transform(), "gua_model_matrix"); + + volume->set_uniforms(ctx, composite_shader_); + + composite_shader_->use(ctx); + { + fullscreen_quad_->draw(ctx.render_context); + } + composite_shader_->unuse(ctx); + } + } + + } + + target->unbind(ctx); + + ctx.render_context->reset_state_objects(); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::init_resources(RenderContext const& ctx) { + if (!initialized_) { + if (!depth_stencil_state_) { + depth_stencil_state_ = ctx.render_device->create_depth_stencil_state(false, false, scm::gl::COMPARISON_NEVER); + } + + if (!fullscreen_quad_) { + fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry(ctx.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); + } + initialized_ = true; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +/* virtual */ LayerMapping const* CompositePass::get_gbuffer_mapping() const { + throw std::runtime_error("no gbuffer mapping available for composite pass"); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::print_shaders(std::string const& directory, + std::string const& name) const { + composite_shader_->save_to_file(directory, name + "/composite_shader"); + ray_generation_shader_->save_to_file(directory, name + "/ray_generation_shader"); +} + +//////////////////////////////////////////////////////////////////////////////// + +bool CompositePass::pre_compile_shaders(RenderContext const& ctx) { + + if (composite_shader_) return composite_shader_->upload_to(ctx); + if (ray_generation_shader_) return ray_generation_shader_->upload_to(ctx); + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::render_scene(Camera const& camera, + SceneGraph const&, + RenderContext const& ctx, + std::size_t viewid) { + + for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { + + FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); + + CameraMode eye(CameraMode::CENTER); + if (gbuffer_->get_eye_buffers().size() > 1 && i == 0) + eye = CameraMode::LEFT; + if (gbuffer_->get_eye_buffers().size() > 1 && i == 1) + eye = CameraMode::RIGHT; + + fbo->bind(ctx); + + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), ::scm::math::vec2f(fbo->width(), fbo->height()))); + + rendering(pipeline_->get_current_scene(eye), ctx, eye, camera, fbo); + + fbo->unbind(ctx); + } +} + +} diff --git a/src/gua/renderer/FullscreenPass.cpp b/src/gua/renderer/FullscreenPass.cpp index 164047169..9a7980530 100644 --- a/src/gua/renderer/FullscreenPass.cpp +++ b/src/gua/renderer/FullscreenPass.cpp @@ -1,88 +1,89 @@ -/****************************************************************************** - * guacamole - delicious VR * - * * - * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * - * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * - * * - * This program is free software: you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the Free * - * Software Foundation, either version 3 of the License, or (at your option) * - * any later version. * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General Public License along * - * with this program. If not, see . * - * * - ******************************************************************************/ - -// class header -#include - -// guacamole headers -#include -#include -#include -#include -#include - -namespace gua { - -//////////////////////////////////////////////////////////////////////////////// - -FullscreenPass::FullscreenPass(Pipeline* pipeline) - : Pass(pipeline), fullscreen_quad_(), depth_stencil_state_() {} - -//////////////////////////////////////////////////////////////////////////////// - -FullscreenPass::~FullscreenPass() {} - -//////////////////////////////////////////////////////////////////////////////// - -void FullscreenPass::render_scene(Camera const& camera, - SceneGraph const&, - RenderContext const& ctx) { - - if (!depth_stencil_state_) - depth_stencil_state_ = ctx.render_device - ->create_depth_stencil_state(false, false, scm::gl::COMPARISON_NEVER); - - if (!fullscreen_quad_) - fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry( - ctx.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); - set_uniforms(pipeline_->get_current_scene(CameraMode::CENTER), ctx); - - for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { - CameraMode eye(CameraMode::CENTER); - - if (gbuffer_->get_eye_buffers().size() > 1 && i == 0) - eye = CameraMode::LEFT; - if (gbuffer_->get_eye_buffers().size() > 1 && i == 1) - eye = CameraMode::RIGHT; - - pre_rendering(camera, pipeline_->get_current_scene(eye), eye, ctx); - - FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); - fbo->bind(ctx); - - ctx.render_context->set_viewport(scm::gl::viewport( - math::vec2(0, 0), math::vec2(float(fbo->width()), float(fbo->height())))); - ctx.render_context->set_depth_stencil_state(depth_stencil_state_); - - rendering(camera, pipeline_->get_current_scene(eye), eye, ctx); - - ctx.render_context->reset_state_objects(); - - fbo->unbind(ctx); - - post_rendering(camera, pipeline_->get_current_scene(eye), eye, ctx); - } - -} - -//////////////////////////////////////////////////////////////////////////////// - -} +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include +#include +#include + +namespace gua { + +//////////////////////////////////////////////////////////////////////////////// + +FullscreenPass::FullscreenPass(Pipeline* pipeline) + : Pass(pipeline), fullscreen_quad_(), depth_stencil_state_() {} + +//////////////////////////////////////////////////////////////////////////////// + +FullscreenPass::~FullscreenPass() {} + +//////////////////////////////////////////////////////////////////////////////// + +void FullscreenPass::render_scene(Camera const& camera, + SceneGraph const&, + RenderContext const& ctx, + std::size_t viewid) { + + if (!depth_stencil_state_) + depth_stencil_state_ = ctx.render_device + ->create_depth_stencil_state(false, false, scm::gl::COMPARISON_NEVER); + + if (!fullscreen_quad_) + fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry( + ctx.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); + set_uniforms(pipeline_->get_current_scene(CameraMode::CENTER), ctx); + + for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { + CameraMode eye(CameraMode::CENTER); + + if (gbuffer_->get_eye_buffers().size() > 1 && i == 0) + eye = CameraMode::LEFT; + if (gbuffer_->get_eye_buffers().size() > 1 && i == 1) + eye = CameraMode::RIGHT; + + pre_rendering(camera, pipeline_->get_current_scene(eye), eye, ctx); + + FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); + fbo->bind(ctx); + + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), math::vec2(float(fbo->width()), float(fbo->height())))); + ctx.render_context->set_depth_stencil_state(depth_stencil_state_); + + rendering(camera, pipeline_->get_current_scene(eye), eye, ctx); + + ctx.render_context->reset_state_objects(); + + fbo->unbind(ctx); + + post_rendering(camera, pipeline_->get_current_scene(eye), eye, ctx); + } + +} + +//////////////////////////////////////////////////////////////////////////////// + +} diff --git a/src/gua/renderer/GBufferPass.cpp b/src/gua/renderer/GBufferPass.cpp index 72cf565b4..fa46db437 100644 --- a/src/gua/renderer/GBufferPass.cpp +++ b/src/gua/renderer/GBufferPass.cpp @@ -45,28 +45,26 @@ namespace gua { //////////////////////////////////////////////////////////////////////////////// GBufferPass::GBufferPass(Pipeline* pipeline) - : GeometryPass(pipeline), - bfc_rasterizer_state_(), - no_bfc_rasterizer_state_(), - bbox_rasterizer_state_(), - depth_stencil_state_() -{} + : GeometryPass(pipeline), + bfc_rasterizer_state_(), + no_bfc_rasterizer_state_(), + bbox_rasterizer_state_(), + depth_stencil_state_() {} //////////////////////////////////////////////////////////////////////////////// -GBufferPass::~GBufferPass() -{} +GBufferPass::~GBufferPass() {} //////////////////////////////////////////////////////////////////////////////// void GBufferPass::create( - RenderContext const& ctx, - std::vector > const& - layers) { + RenderContext const& ctx, + std::vector > const& + layers) { scm::gl::sampler_state_desc state(scm::gl::FILTER_MIN_MAG_MIP_NEAREST, - scm::gl::WRAP_MIRRORED_REPEAT, - scm::gl::WRAP_MIRRORED_REPEAT); + scm::gl::WRAP_MIRRORED_REPEAT, + scm::gl::WRAP_MIRRORED_REPEAT); auto tmp(layers); tmp.insert(tmp.begin(), std::make_pair(BufferComponent::DEPTH_24, state)); @@ -74,17 +72,14 @@ void GBufferPass::create( Pass::create(ctx, tmp); } - //////////////////////////////////////////////////////////////////////////////// -void GBufferPass::cleanup(RenderContext const& ctx) { - Pass::cleanup(ctx); -} +void GBufferPass::cleanup(RenderContext const& ctx) { Pass::cleanup(ctx); } //////////////////////////////////////////////////////////////////////////////// -bool GBufferPass::pre_compile_shaders(const gua::RenderContext & ctx) { - bool success {true}; +bool GBufferPass::pre_compile_shaders(const gua::RenderContext& ctx) { + bool success{true}; for (auto const& shader : ubershaders_) { success &= shader.second->upload_to(ctx); @@ -96,22 +91,21 @@ bool GBufferPass::pre_compile_shaders(const gua::RenderContext & ctx) { //////////////////////////////////////////////////////////////////////////////// void GBufferPass::rendering(SerializedScene const& scene, - SceneGraph const& graph, - RenderContext const& ctx, - CameraMode eye, - Camera const& camera, - FrameBufferObject* target) { - - if (!depth_stencil_state_ || - !bfc_rasterizer_state_ || - !no_bfc_rasterizer_state_ || + SceneGraph const& graph, + RenderContext const& ctx, + CameraMode eye, + Camera const& camera, + FrameBufferObject* target, + std::size_t viewid) { + + if (!depth_stencil_state_ || !bfc_rasterizer_state_ || !no_bfc_rasterizer_state_) { initialize_state_objects(ctx); } ctx.render_context->set_rasterizer_state( - pipeline_->config.enable_backface_culling() ? bfc_rasterizer_state_ - : no_bfc_rasterizer_state_); + pipeline_->config.enable_backface_culling() ? bfc_rasterizer_state_ + : no_bfc_rasterizer_state_); ctx.render_context->set_depth_stencil_state(depth_stencil_state_); @@ -125,20 +119,22 @@ void GBufferPass::rendering(SerializedScene const& scene, auto ubershader = ubershaders_.at(type); // set frame-consistent per-ubershader uniforms - ubershader->set_material_uniforms(scene.materials_, ShadingModel::GBUFFER_VERTEX_STAGE, ctx); - ubershader->set_material_uniforms(scene.materials_, ShadingModel::GBUFFER_FRAGMENT_STAGE, ctx); - - ubershader->set_uniform(ctx, scene.enable_global_clipping_plane, "gua_enable_global_clipping_plane"); - ubershader->set_uniform(ctx, scene.global_clipping_plane, "gua_global_clipping_plane"); + ubershader->set_material_uniforms( + scene.materials_, ShadingModel::GBUFFER_VERTEX_STAGE, ctx); + ubershader->set_material_uniforms( + scene.materials_, ShadingModel::GBUFFER_FRAGMENT_STAGE, ctx); + + ubershader->set_uniform(ctx, + scene.enable_global_clipping_plane, + "gua_enable_global_clipping_plane"); + ubershader->set_uniform( + ctx, scene.global_clipping_plane, "gua_global_clipping_plane"); ubershader->set_uniform(ctx, false, "gua_render_shadow_map"); for (auto const& program : ubershader->programs()) { Pass::bind_inputs(*program, eye, ctx); - Pass::set_camera_matrices(*program, - camera, - pipeline_->get_current_scene(eye), - eye, - ctx); + Pass::set_camera_matrices( + *program, camera, pipeline_->get_current_scene(eye), eye, ctx); } // 1. call preframe callback if available for type @@ -146,53 +142,101 @@ void GBufferPass::rendering(SerializedScene const& scene, ubershader->preframe(ctx); } - // 2. iterate all drawables of current type and call predraw of current ubershader + // 2. iterate all drawables of current type and call predraw of current + // ubershader if (ubershader->get_stage_mask() & GeometryUberShader::PRE_DRAW_STAGE) { for (auto const& node : ressource_container) { - auto const& ressource = GeometryDatabase::instance()->lookup(node->get_filename()); - auto const& material = MaterialDatabase::instance()->lookup(node->get_material()); + auto const& ressource = + GeometryDatabase::instance()->lookup(node->get_filename()); + auto const& material = + MaterialDatabase::instance()->lookup(node->get_material()); if (ressource && material) { ubershader->predraw(ctx, - node->get_filename(), - node->get_material(), - node->get_cached_world_transform(), - scm::math::transpose(scm::math::inverse(node->get_cached_world_transform())), - scene.frustum); + node->get_filename(), + node->get_material(), + node->get_cached_world_transform(), + scm::math::transpose(scm::math::inverse( + node->get_cached_world_transform())), + scene.frustum, + viewid); + } else { + if (!material) { + Logger::LOG_WARNING + << "GBufferPass::rendering() Cannot find material. " << material + << std::endl; + } + if (!ressource) { + Logger::LOG_WARNING + << "GBufferPass::rendering() Cannot find geometry ressource." + << ressource << std::endl; + } } } } - // 3. iterate all drawables of current type and call draw of current ubershader + // 3. iterate all drawables of current type and call draw of current + // ubershader if (ubershader->get_stage_mask() & GeometryUberShader::DRAW_STAGE) { for (auto const& node : ressource_container) { - auto const& ressource = GeometryDatabase::instance()->lookup(node->get_filename()); - auto const& material = MaterialDatabase::instance()->lookup(node->get_material()); + auto const& ressource = + GeometryDatabase::instance()->lookup(node->get_filename()); + auto const& material = + MaterialDatabase::instance()->lookup(node->get_material()); if (ressource && material) { ubershader->draw(ctx, - node->get_filename(), - node->get_material(), - node->get_cached_world_transform(), - scm::math::transpose(scm::math::inverse(node->get_cached_world_transform())), - scene.frustum); + node->get_filename(), + node->get_material(), + node->get_cached_world_transform(), + scm::math::transpose(scm::math::inverse( + node->get_cached_world_transform())), + scene.frustum, + viewid); + } else { + if (!material) { + Logger::LOG_WARNING + << "GBufferPass::rendering() Cannot find material. " << material + << std::endl; + } + if (!ressource) { + Logger::LOG_WARNING + << "GBufferPass::rendering() Cannot find geometry ressource." + << ressource << std::endl; + } } } } - // 4. iterate all drawables of current type and call postdraw of current ubershader + // 4. iterate all drawables of current type and call postdraw of current + // ubershader if (ubershader->get_stage_mask() & GeometryUberShader::POST_DRAW_STAGE) { for (auto const& node : ressource_container) { - auto const& ressource = GeometryDatabase::instance()->lookup(node->get_filename()); - auto const& material = MaterialDatabase::instance()->lookup(node->get_material()); + auto const& ressource = + GeometryDatabase::instance()->lookup(node->get_filename()); + auto const& material = + MaterialDatabase::instance()->lookup(node->get_material()); if (ressource && material) { ubershader->postdraw(ctx, - node->get_filename(), - node->get_material(), - node->get_cached_world_transform(), - scm::math::transpose(scm::math::inverse(node->get_cached_world_transform())), - scene.frustum); + node->get_filename(), + node->get_material(), + node->get_cached_world_transform(), + scm::math::transpose(scm::math::inverse( + node->get_cached_world_transform())), + scene.frustum, + viewid); + } else { + if (!material) { + Logger::LOG_WARNING + << "GBufferPass::rendering() Cannot find material. " << material + << std::endl; + } + if (!ressource) { + Logger::LOG_WARNING + << "GBufferPass::rendering() Cannot find geometry ressource." + << ressource << std::endl; + } } } } @@ -206,29 +250,29 @@ void GBufferPass::rendering(SerializedScene const& scene, /////////////////////////////////////////////////////////////// // draw debug and helper information /////////////////////////////////////////////////////////////// - display_quads(ctx, scene, eye); + display_quads(ctx, scene, eye, viewid); ctx.render_context->set_rasterizer_state(bbox_rasterizer_state_); - display_bboxes(ctx, scene); - display_rays(ctx, scene); + display_bboxes(ctx, scene, viewid); + display_rays(ctx, scene, viewid); ctx.render_context->reset_state_objects(); } //////////////////////////////////////////////////////////////////////////////// -void GBufferPass::display_bboxes(RenderContext const& ctx, SerializedScene const& scene) -{ +void GBufferPass::display_bboxes(RenderContext const& ctx, + SerializedScene const& scene, + std::size_t viewid) { auto meshubershader = Singleton::instance(); - if (pipeline_->config.enable_bbox_display()) - { + if (pipeline_->config.enable_bbox_display()) { meshubershader->get_program()->use(ctx); - for (auto const& bbox : scene.bounding_boxes_) - { + for (auto const& bbox : scene.bounding_boxes_) { auto scale(scm::math::make_scale((bbox.max - bbox.min) * 1.001f)); - auto translation(scm::math::make_translation((bbox.max + bbox.min) / 2.f)); + auto translation( + scm::math::make_translation((bbox.max + bbox.min) / 2.f)); scm::math::mat4 bbox_transform; scm::math::set_identity(bbox_transform); @@ -236,35 +280,43 @@ void GBufferPass::display_bboxes(RenderContext const& ctx, SerializedScene const bbox_transform *= translation; bbox_transform *= scale; - meshubershader->draw(ctx, - "gua_bounding_box_geometry", - "gua_bounding_box", - bbox_transform, - scm::math::transpose(scm::math::inverse(bbox_transform)), - scene.frustum); + bbox_transform *= translation; + bbox_transform *= scale; + + meshubershader->draw( + ctx, + "gua_bounding_box_geometry", + "gua_bounding_box", + bbox_transform, + scm::math::transpose(scm::math::inverse(bbox_transform)), + scene.frustum, + viewid); } meshubershader->get_program()->unuse(ctx); } } - //////////////////////////////////////////////////////////////////////////////// -void GBufferPass::display_rays(RenderContext const& ctx, SerializedScene const& scene) -{ - auto meshubershader = Singleton::instance(); +void GBufferPass::display_rays(RenderContext const& ctx, + SerializedScene const& scene, + std::size_t viewid) { + auto meshubershader = Singleton::instance(); - if (pipeline_->config.enable_ray_display()) - { + if (pipeline_->config.enable_ray_display()) { meshubershader->get_program()->use(ctx); - for (auto const& ray : scene.rays_) - { - meshubershader->draw(ctx, - "gua_plane_geometry", - "gua_bounding_box", - ray->get_cached_world_transform(), - scm::math::inverse(ray->get_cached_world_transform()), - scene.frustum); + for (auto const& ray : scene.rays_) { + meshubershader->get_program()->use(ctx); + for (auto const& ray : scene.rays_) { + meshubershader->draw( + ctx, + "gua_plane_geometry", + "gua_bounding_box", + ray->get_cached_world_transform(), + scm::math::inverse(ray->get_cached_world_transform()), + scene.frustum, + viewid); + } } meshubershader->get_program()->unuse(ctx); } @@ -272,71 +324,78 @@ void GBufferPass::display_rays(RenderContext const& ctx, SerializedScene const& //////////////////////////////////////////////////////////////////////////////// -void GBufferPass::display_quads(RenderContext const& ctx, SerializedScene const& scene, CameraMode eye) -{ +void GBufferPass::display_quads(RenderContext const& ctx, + SerializedScene const& scene, + CameraMode eye, + std::size_t viewid) { auto meshubershader = Singleton::instance(); if (!scene.textured_quads_.empty()) { meshubershader->get_program()->use(ctx); { - for (auto const& node : scene.textured_quads_) - { + for (auto const& node : scene.textured_quads_) { std::string texture_name(node->get_texture()); if (node->is_stereo_texture()) { if (eye == CameraMode::LEFT) { texture_name += "_left"; - } - else if (eye == CameraMode::RIGHT) { + } else if (eye == CameraMode::RIGHT) { texture_name += "_right"; } } - if (TextureDatabase::instance()->is_supported(texture_name)) - { + if (TextureDatabase::instance()->is_supported(texture_name)) { auto texture = TextureDatabase::instance()->lookup(texture_name); - auto mapped_texture(meshubershader->get_uniform_mapping()->get_mapping("gua_textured_quad", "texture")); - - meshubershader->set_uniform(ctx, texture, mapped_texture.first, mapped_texture.second); - - auto mapped_flip_x(meshubershader->get_uniform_mapping()->get_mapping("gua_textured_quad", "flip_x")); - meshubershader->set_uniform(ctx, node->flip_x(), mapped_flip_x.first, mapped_flip_x.second); - - auto mapped_flip_y(meshubershader->get_uniform_mapping()->get_mapping("gua_textured_quad", "flip_y")); - meshubershader->set_uniform(ctx, node->flip_y(), mapped_flip_y.first, mapped_flip_y.second); + auto mapped_texture( + meshubershader->get_uniform_mapping()->get_mapping( + "gua_textured_quad", "texture")); + + meshubershader->set_uniform( + ctx, texture, mapped_texture.first, mapped_texture.second); + + auto mapped_flip_x(meshubershader->get_uniform_mapping()->get_mapping( + "gua_textured_quad", "flip_x")); + meshubershader->set_uniform( + ctx, node->flip_x(), mapped_flip_x.first, mapped_flip_x.second); + + auto mapped_flip_y(meshubershader->get_uniform_mapping()->get_mapping( + "gua_textured_quad", "flip_y")); + meshubershader->set_uniform( + ctx, node->flip_y(), mapped_flip_y.first, mapped_flip_y.second); } - meshubershader->draw(ctx, - "gua_plane_geometry", - "gua_textured_quad", - node->get_scaled_world_transform(), - scm::math::inverse(node->get_scaled_world_transform()), - scene.frustum); + meshubershader->draw( + ctx, + "gua_plane_geometry", + "gua_textured_quad", + node->get_scaled_world_transform(), + scm::math::inverse(node->get_scaled_world_transform()), + scene.frustum, + viewid); } } meshubershader->get_program()->unuse(ctx); } } - //////////////////////////////////////////////////////////////////////////////// -void GBufferPass::update_ubershader_from_scene(SerializedScene const& scene, SceneGraph const& graph) -{ +void GBufferPass::update_ubershader_from_scene(SerializedScene const& scene, + SceneGraph const& graph) { bool ubershader_available = true; - for (auto const& geometry_pair : scene.geometrynodes_) - { - ubershader_available = ubershader_available && ubershaders_.count(geometry_pair.first); + for (auto const& geometry_pair : scene.geometrynodes_) { + ubershader_available = + ubershader_available && ubershaders_.count(geometry_pair.first); } - if (!ubershader_available) - { - auto get_ubershader = [&] (Node* n) { + if (!ubershader_available) { + auto get_ubershader = [&](Node * n) { GeometryNode* geode = dynamic_cast(n); if (geode) { std::type_index type(typeid(*geode)); if (!ubershaders_.count(type)) { - auto const& ressource = GeometryDatabase::instance()->lookup(geode->get_filename()); + auto const& ressource = + GeometryDatabase::instance()->lookup(geode->get_filename()); if (ressource) { auto ubershader = ressource->get_ubershader(); ubershader->create(materials_); @@ -344,54 +403,50 @@ void GBufferPass::update_ubershader_from_scene(SerializedScene const& scene, Sce } } } - }; + } + ; gua::dfs_traverse(graph.get_root().get(), get_ubershader); } } //////////////////////////////////////////////////////////////////////////////// -void GBufferPass::initialize_state_objects(RenderContext const& ctx) -{ +void GBufferPass::initialize_state_objects(RenderContext const& ctx) { if (!depth_stencil_state_) depth_stencil_state_ = - ctx.render_device->create_depth_stencil_state(true, true); + ctx.render_device->create_depth_stencil_state(true, true); if (!bfc_rasterizer_state_) bfc_rasterizer_state_ = ctx.render_device->create_rasterizer_state( - pipeline_->config.enable_wireframe() ? scm::gl::FILL_WIREFRAME - : scm::gl::FILL_SOLID, - scm::gl::CULL_BACK, - scm::gl::ORIENT_CCW, - false); + pipeline_->config.enable_wireframe() ? scm::gl::FILL_WIREFRAME + : scm::gl::FILL_SOLID, + scm::gl::CULL_BACK, + scm::gl::ORIENT_CCW, + false); if (!no_bfc_rasterizer_state_) no_bfc_rasterizer_state_ = ctx.render_device->create_rasterizer_state( - pipeline_->config.enable_wireframe() ? scm::gl::FILL_WIREFRAME - : scm::gl::FILL_SOLID, - scm::gl::CULL_NONE); + pipeline_->config.enable_wireframe() ? scm::gl::FILL_WIREFRAME + : scm::gl::FILL_SOLID, + scm::gl::CULL_NONE); if (!bbox_rasterizer_state_) bbox_rasterizer_state_ = ctx.render_device - ->create_rasterizer_state(scm::gl::FILL_SOLID, scm::gl::CULL_NONE); + ->create_rasterizer_state(scm::gl::FILL_SOLID, scm::gl::CULL_NONE); } - //////////////////////////////////////////////////////////////////////////////// -void GBufferPass::apply_material_mapping(std::set const& materials) -{ +void GBufferPass::apply_material_mapping( + std::set const& materials) { materials_ = materials; Singleton::instance()->create(materials_); } - //////////////////////////////////////////////////////////////////////////////// LayerMapping const* GBufferPass::get_gbuffer_mapping() const { return Singleton::instance()->get_gbuffer_mapping(); } - } - diff --git a/src/gua/renderer/GeometryPass.cpp b/src/gua/renderer/GeometryPass.cpp index fa765a2f8..375670468 100644 --- a/src/gua/renderer/GeometryPass.cpp +++ b/src/gua/renderer/GeometryPass.cpp @@ -1,69 +1,70 @@ -/****************************************************************************** - * guacamole - delicious VR * - * * - * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * - * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * - * * - * This program is free software: you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the Free * - * Software Foundation, either version 3 of the License, or (at your option) * - * any later version. * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General Public License along * - * with this program. If not, see . * - * * - ******************************************************************************/ - -// class header -#include - -// guacamole headers -#include -#include -#include -#include -#include - -namespace gua { - -//////////////////////////////////////////////////////////////////////////////// - -GeometryPass::GeometryPass(Pipeline* pipeline) : Pass(pipeline) {} - -//////////////////////////////////////////////////////////////////////////////// - -void GeometryPass::render_scene(Camera const& camera, - SceneGraph const& current_graph, - RenderContext const& ctx) { - - gbuffer_->clear(ctx); - - for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { - - FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); - - CameraMode eye(CameraMode::CENTER); - if (gbuffer_->get_eye_buffers().size() > 1 && i == 0) - eye = CameraMode::LEFT; - if (gbuffer_->get_eye_buffers().size() > 1 && i == 1) - eye = CameraMode::RIGHT; - - fbo->bind(ctx); - - ctx.render_context->set_viewport(scm::gl::viewport( - math::vec2(0, 0), ::scm::math::vec2f(fbo->width(), fbo->height()))); - - rendering(pipeline_->get_current_scene(eye), current_graph, ctx, eye, camera, fbo); - - fbo->unbind(ctx); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -} +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include +#include +#include + +namespace gua { + +//////////////////////////////////////////////////////////////////////////////// + +GeometryPass::GeometryPass(Pipeline* pipeline) : Pass(pipeline) {} + +//////////////////////////////////////////////////////////////////////////////// + +void GeometryPass::render_scene(Camera const& camera, + SceneGraph const& current_graph, + RenderContext const& ctx, + std::size_t viewid) { + + gbuffer_->clear(ctx); + + for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { + + FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); + + CameraMode eye(CameraMode::CENTER); + if (gbuffer_->get_eye_buffers().size() > 1 && i == 0) + eye = CameraMode::LEFT; + if (gbuffer_->get_eye_buffers().size() > 1 && i == 1) + eye = CameraMode::RIGHT; + + fbo->bind(ctx); + + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), ::scm::math::vec2f(fbo->width(), fbo->height()))); + + rendering(pipeline_->get_current_scene(eye), current_graph, ctx, eye, camera, fbo, viewid); + + fbo->unbind(ctx); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +} diff --git a/src/gua/renderer/LightingPass.cpp b/src/gua/renderer/LightingPass.cpp index 89e0576a0..62c294356 100644 --- a/src/gua/renderer/LightingPass.cpp +++ b/src/gua/renderer/LightingPass.cpp @@ -132,7 +132,8 @@ void LightingPass::rendering(SerializedScene const& scene, RenderContext const& ctx, CameraMode eye, Camera const& camera, - FrameBufferObject* target) { + FrameBufferObject* target, + std::size_t viewid) { init_resources(ctx); ctx.render_context->set_depth_stencil_state(depth_stencil_state_); diff --git a/src/gua/renderer/NURBSLoader.cpp b/src/gua/renderer/NURBSLoader.cpp index 88a744415..54ec52cb2 100644 --- a/src/gua/renderer/NURBSLoader.cpp +++ b/src/gua/renderer/NURBSLoader.cpp @@ -57,21 +57,22 @@ std::shared_ptr NURBSLoader::create_geometry_from_file(std::string const& throw std::runtime_error(std::string("Unsupported filetype: ") + filename); } else { + igs_loader igsloader; TrimmedSurfaceConverter surface_converter; - std::shared_ptr nurbs_object( - new TrimmedNurbsSurfaceObject); - std::shared_ptr bezier_object( - new TrimmedBezierSurfaceObject); + auto nurbs_object = std::make_shared(); + auto bezier_object = std::make_shared(); igsloader.load(filename, nurbs_object); surface_converter.convert(nurbs_object, bezier_object); auto ressource = std::make_shared(bezier_object); - GeometryDatabase::instance()->add(filename, ressource); - auto node = std::make_shared(nodename, filename, material); + std::string mesh_name("type=file&file=" + filename + "&flags=" + string_utils::to_string(flags)); + GeometryDatabase::instance()->add(mesh_name, ressource); + + auto node = std::make_shared(nodename, mesh_name, material); node->update_cache(); return node; diff --git a/src/gua/renderer/NURBSRessource.cpp b/src/gua/renderer/NURBSRessource.cpp index a2fd6d573..5d7665699 100644 --- a/src/gua/renderer/NURBSRessource.cpp +++ b/src/gua/renderer/NURBSRessource.cpp @@ -47,7 +47,6 @@ NURBSRessource::NURBSRessource(std::shared_ptr const object->bbox().min[0], object->bbox().min[1], object->bbox().min[2]), math::vec3( object->bbox().max[0], object->bbox().max[1], object->bbox().max[2])); - std::cout << object->bbox() << std::endl; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/renderer/NURBSUberShader.cpp b/src/gua/renderer/NURBSUberShader.cpp index f3946efb0..3f3c5d527 100644 --- a/src/gua/renderer/NURBSUberShader.cpp +++ b/src/gua/renderer/NURBSUberShader.cpp @@ -731,30 +731,31 @@ std::string const NURBSUberShader::_final_geometry_shader () const geom_shader << method.second << std::endl; } - geom_shader << std::string(" \n\ - void main() \n\ - { \n\ - for ( int i = 0; i != 3; ++i ) \n\ - { \n\ - gIndex = teIndex[i]; \n\ - gTessCoord = teTessCoord[i]; \n\ - \n\ - // write built-in input for material \n\ - /////////////////////////////////////////////////////// \n\ - gua_texcoords = gTessCoord; \n\ - \n\ - gua_position_varying = (gua_model_matrix * tePosition[i]).xyz; \n\ - gua_object_normal = teNormal[i].xyz; \n\ - gua_object_tangent = teTangent[i].xyz; \n\ - gua_object_bitangent = teBitangent[i].xyz; \n\ - gua_object_position = tePosition[i].xyz; \n\ - \n\ - gua_world_normal = normalize ( gua_normal_matrix * vec4 (teNormal[i].xyz, 0.0) ).xyz; \n\ - gua_world_tangent = normalize ( gua_normal_matrix * vec4 (teTangent[i].xyz, 0.0) ).xyz; \n\ - gua_world_bitangent = normalize ( gua_normal_matrix * vec4 (teBitangent[i].xyz, 0.0) ).xyz; \n\ - gua_world_position = (gua_model_matrix * tePosition[i]).xyz; \n\ - /////////////////////////////////////////////////////// \n\ - "); + geom_shader << R"( + void main() + { + for ( int i = 0; i != 3; ++i ) + { + gIndex = teIndex[i]; + gTessCoord = teTessCoord[i]; + + // write built-in input for material + /////////////////////////////////////////////////////// + gua_texcoords = gTessCoord; + + gua_position_varying = (gua_model_matrix * tePosition[i]).xyz; + gua_object_normal = teNormal[i].xyz; + gua_object_tangent = teTangent[i].xyz; + gua_object_bitangent = teBitangent[i].xyz; + gua_object_position = tePosition[i].xyz; + + vec4 world_normal = gua_normal_matrix * vec4 (teNormal[i].xyz, 0.0); + gua_world_normal = normalize ( world_normal.xyz ); + gua_world_tangent = normalize ( gua_normal_matrix * vec4 (teTangent[i].xyz, 0.0) ).xyz; + gua_world_bitangent = normalize ( gua_normal_matrix * vec4 (teBitangent[i].xyz, 0.0) ).xyz; + gua_world_position = (gua_model_matrix * tePosition[i]).xyz; + /////////////////////////////////////////////////////// + )"; // generated code auto main_calls(vshader_factory_->get_main_calls()); @@ -948,7 +949,8 @@ std::string const NURBSUberShader::_final_fragment_shader () const std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t viewid) const { throw std::runtime_error("NURBSUberShader::predraw(): not implemented"); } @@ -961,31 +963,30 @@ void NURBSUberShader::draw(RenderContext const& ctx, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const { auto geometry = std::static_pointer_cast(GeometryDatabase::instance()->lookup(filename)); auto material = MaterialDatabase::instance()->lookup(material_name); - if ( geometry && material ) - { - set_uniform(ctx, 128, "gua_max_tesselation"); - set_uniform(ctx, material->get_id(), "gua_material_id"); - set_uniform(ctx, model_matrix, "gua_model_matrix"); - set_uniform(ctx, normal_matrix, "gua_normal_matrix"); + set_uniform(ctx, 128, "gua_max_tesselation"); + set_uniform(ctx, material->get_id(), "gua_material_id"); + set_uniform(ctx, model_matrix, "gua_model_matrix"); + set_uniform(ctx, normal_matrix, "gua_normal_matrix"); #ifdef DEBUG_XFB_OUTPUT scm::gl::transform_feedback_statistics_query_ptr q = ctx .render_device->create_transform_feedback_statistics_query(0); ctx.render_context->begin_query(q); - #endif +#endif - // pre-tesselate if necessary - get_program(transform_feedback_pass)->use(ctx); - { - ctx.render_context->apply(); - geometry->predraw(ctx); - } - get_program(transform_feedback_pass)->unuse(ctx); + // pre-tesselate if necessary + get_program(transform_feedback_pass)->use(ctx); + { + ctx.render_context->apply(); + geometry->predraw(ctx); + } + get_program(transform_feedback_pass)->unuse(ctx); #ifdef DEBUG_XFB_OUTPUT ctx.render_context->end_query(q); @@ -994,14 +995,14 @@ void NURBSUberShader::draw(RenderContext const& ctx, << q->result()._primitives_written << std::endl; #endif - // invoke tesselation/trim shader for adaptive nurbs rendering - get_program(final_pass)->use(ctx); - { - ctx.render_context->apply(); - geometry->draw(ctx); - } - get_program(final_pass)->unuse(ctx); + // invoke tesselation/trim shader for adaptive nurbs rendering + get_program(final_pass)->use(ctx); + { + ctx.render_context->apply(); + geometry->draw(ctx); } + get_program(final_pass)->unuse(ctx); + } //////////////////////////////////////////////////////////////////////////////// @@ -1011,7 +1012,8 @@ void NURBSUberShader::draw(RenderContext const& ctx, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const { throw std::runtime_error("NURBSUberShader::postdraw(): not implemented"); } diff --git a/src/gua/renderer/Pipeline.cpp b/src/gua/renderer/Pipeline.cpp index e8758d945..934cdc531 100644 --- a/src/gua/renderer/Pipeline.cpp +++ b/src/gua/renderer/Pipeline.cpp @@ -275,7 +275,7 @@ void Pipeline::process(std::vector> const& sce } for (auto pass : passes_) { - pass->render_scene(config.camera(), *current_graph, *context_); + pass->render_scene(config.camera(), *current_graph, *context_, uuid()); } if (window_) { diff --git a/src/gua/renderer/PostFXPass.cpp b/src/gua/renderer/PostFXPass.cpp index c6ff54cdb..3cd4a320f 100644 --- a/src/gua/renderer/PostFXPass.cpp +++ b/src/gua/renderer/PostFXPass.cpp @@ -284,9 +284,12 @@ void PostFXPass::init_resources(RenderContext const& ctx) { } } +//////////////////////////////////////////////////////////////////////////////// + void PostFXPass::render_scene(Camera const& camera, SceneGraph const&, - RenderContext const& ctx) { + RenderContext const& ctx, + std::size_t viewid) { init_resources(ctx); ctx.render_context->set_depth_stencil_state(depth_stencil_state_); diff --git a/src/gua/renderer/ShadowMap.cpp b/src/gua/renderer/ShadowMap.cpp index ca9328907..d2da73eae 100644 --- a/src/gua/renderer/ShadowMap.cpp +++ b/src/gua/renderer/ShadowMap.cpp @@ -177,7 +177,8 @@ void ShadowMap::render_geometry(RenderContext const & ctx, node->get_material(), node->get_cached_world_transform(), scm::math::transpose(scm::math::inverse(node->get_cached_world_transform())), - scene.frustum); + scene.frustum, + uuid()); } } else { Logger::LOG_WARNING << "ShadowMap::render_geometry(): UberShader missing." << std::endl; diff --git a/src/gua/renderer/TriMeshLoader.cpp b/src/gua/renderer/TriMeshLoader.cpp index ddea8c552..048ae5a0e 100644 --- a/src/gua/renderer/TriMeshLoader.cpp +++ b/src/gua/renderer/TriMeshLoader.cpp @@ -307,6 +307,7 @@ void TriMeshLoader::apply_fallback_material(std::shared_ptr const& root, if (g_node) { if (g_node->get_material().empty()) { g_node->set_material(fallback_material); + g_node->update_cache(); } } @@ -314,6 +315,7 @@ void TriMeshLoader::apply_fallback_material(std::shared_ptr const& root, apply_fallback_material(child, fallback_material); } + } } diff --git a/src/gua/renderer/TriMeshUberShader.cpp b/src/gua/renderer/TriMeshUberShader.cpp index a12289b12..24395dce9 100644 --- a/src/gua/renderer/TriMeshUberShader.cpp +++ b/src/gua/renderer/TriMeshUberShader.cpp @@ -110,7 +110,8 @@ namespace gua { std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const { throw std::runtime_error("TriMeshUberShader::predraw(): not implemented"); } @@ -122,21 +123,19 @@ namespace gua { std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const { auto geometry = std::static_pointer_cast(GeometryDatabase::instance()->lookup(filename)); auto material = MaterialDatabase::instance()->lookup(material_name); get_program()->use(ctx); { - if (material && geometry) - { - set_uniform(ctx, material->get_id(), "gua_material_id"); - set_uniform(ctx, model_matrix, "gua_model_matrix"); - set_uniform(ctx, normal_matrix, "gua_normal_matrix"); - - geometry->draw(ctx); - } + set_uniform(ctx, material->get_id(), "gua_material_id"); + set_uniform(ctx, model_matrix, "gua_model_matrix"); + set_uniform(ctx, normal_matrix, "gua_normal_matrix"); + + geometry->draw(ctx); } get_program()->unuse(ctx); } @@ -148,7 +147,8 @@ namespace gua { std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t /*viewid*/) const { throw std::runtime_error("TriMeshUberShader::postdraw(): not implemented"); } diff --git a/src/gua/renderer/Video3DUberShader.cpp b/src/gua/renderer/Video3DUberShader.cpp index 8279e1850..309ac762f 100644 --- a/src/gua/renderer/Video3DUberShader.cpp +++ b/src/gua/renderer/Video3DUberShader.cpp @@ -235,14 +235,19 @@ bool Video3DUberShader::upload_to (RenderContext const& context) const if (context.id >= depth_stencil_state_warp_pass_.size()) { depth_stencil_state_warp_pass_.resize(context.id + 1); - depth_stencil_state_warp_pass_[context.id] = context.render_device->create_depth_stencil_state(false, true, scm::gl::COMPARISON_NEVER); + depth_stencil_state_warp_pass_[context.id] = context.render_device->create_depth_stencil_state(true, true, scm::gl::COMPARISON_LESS); } if (context.id >= depth_stencil_state_blend_pass_.size()) { depth_stencil_state_blend_pass_.resize(context.id + 1); - depth_stencil_state_blend_pass_[context.id] = context.render_device->create_depth_stencil_state(false, true, scm::gl::COMPARISON_NEVER); + depth_stencil_state_blend_pass_[context.id] = context.render_device->create_depth_stencil_state(true, true, scm::gl::COMPARISON_LESS); } - + if (context.id >= no_bfc_rasterizer_state_.size()) + { + no_bfc_rasterizer_state_.resize(context.id + 1); + no_bfc_rasterizer_state_[context.id] = context.render_device->create_rasterizer_state(scm::gl::FILL_SOLID, scm::gl::CULL_NONE); + } + return upload_succeeded; } @@ -267,7 +272,8 @@ bool Video3DUberShader::upload_to (RenderContext const& context) const std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t viewid) const { throw std::runtime_error("not implemented"); } @@ -280,7 +286,8 @@ void Video3DUberShader::draw(RenderContext const& ctx, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t viewid) const { if (!GeometryDatabase::instance()->is_supported(ksfile_name) || !MaterialDatabase::instance()->is_supported(material_name)) { @@ -305,12 +312,13 @@ void Video3DUberShader::draw(RenderContext const& ctx, // single texture only scm::gl::context_all_guard guard(ctx.render_context); + ctx.render_context->set_rasterizer_state(no_bfc_rasterizer_state_[ctx.id]); + ctx.render_context->set_depth_stencil_state(depth_stencil_state_warp_pass_[ctx.id]); + + // set uniforms ctx.render_context->bind_texture(video3d_ressource->depth_array(ctx), nearest_sampler_state_[ctx.id], 0); get_program(warp_pass)->get_program(ctx)->uniform_sampler("depth_video3d_texture", 0); - auto ds_state = ctx.render_device->create_depth_stencil_state(true, true, scm::gl::COMPARISON_LESS); - ctx.render_context->set_depth_stencil_state(ds_state); - scm::math::vec4f norm_vec (0.0f, 1.0f, 0.0f, 0.0f); auto trans_vec = model_matrix * norm_vec; @@ -371,6 +379,8 @@ void Video3DUberShader::draw(RenderContext const& ctx, // single texture only scm::gl::context_all_guard guard(ctx.render_context); + ctx.render_context->set_depth_stencil_state(depth_stencil_state_warp_pass_[ctx.id]); + // second pass get_program(blend_pass)->use(ctx); { @@ -409,7 +419,8 @@ void Video3DUberShader::draw(RenderContext const& ctx, std::string const& material_name, scm::math::mat4 const& model_matrix, scm::math::mat4 const& normal_matrix, - Frustum const& /*frustum*/) const + Frustum const& /*frustum*/, + std::size_t viewid) const { throw std::runtime_error("not implemented"); } diff --git a/src/gua/scenegraph/GeometryNode.cpp b/src/gua/scenegraph/GeometryNode.cpp index b0cfb53f0..6874734a0 100644 --- a/src/gua/scenegraph/GeometryNode.cpp +++ b/src/gua/scenegraph/GeometryNode.cpp @@ -43,11 +43,9 @@ namespace gua { filename_(filename), material_(material), shadow_mode_(shadow_mode), - filename_changed_(false), - material_changed_(false) - { - cache_material(); - } + filename_changed_(true), + material_changed_(true) + {} //////////////////////////////////////////////////////////////////////////////// std::string const& GeometryNode::get_filename() const { @@ -74,7 +72,6 @@ namespace gua { void GeometryNode::set_material(std::string const& v) { material_ = v; material_changed_ = self_dirty_ = true; - cache_material(); } //////////////////////////////////////////////////////////////////////////////// @@ -92,16 +89,4 @@ namespace gua { Node::update_bounding_box(); } } - - //////////////////////////////////////////////////////////////////////////////// - void GeometryNode::cache_material() const - { - if (!material_.empty()) - { - if (!MaterialDatabase::instance()->is_supported(material_)) - { - MaterialDatabase::instance()->load_material(material_); - } - } - } } diff --git a/src/gua/scenegraph/NURBSNode.cpp b/src/gua/scenegraph/NURBSNode.cpp index 221459a33..5968473af 100644 --- a/src/gua/scenegraph/NURBSNode.cpp +++ b/src/gua/scenegraph/NURBSNode.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include // guacamole headers @@ -49,6 +49,81 @@ namespace gua { Logger::LOG_WARNING << "NURBSNode::ray_test_impl() : Ray test not implemented yet for NURBS" << std::endl; } + //////////////////////////////////////////////////////////////////////////////// + + void NURBSNode::update_cache() { + + // The code below auto-loads a geometry if it's not already supported by + // the GeometryDatabase. It expects a geometry name like + // + // "type='file'&file='data/objects/monkey.obj'&id=0&flags=0" + + if (filename_changed_) + { + if (filename_ != "") + { + if (!GeometryDatabase::instance()->is_supported(filename_)) + { + auto params(string_utils::split(filename_, '&')); + + if (params.size() == 4) + { + if (params[0] == "type=file") + { + auto tmp_filename(string_utils::split(params[1], '=')); + auto tmp_flags(string_utils::split(params[2], '=')); + + if (tmp_filename.size() == 2 && tmp_flags.size() == 2) + { + std::string filename(tmp_filename[1]); + std::string flags_string(tmp_flags[1]); + unsigned flags(0); + std::stringstream sstr(flags_string); + sstr >> flags; + + NURBSLoader loader; + + // node is deleted directly after initialization, but ressources remain in database + loader.create_geometry_from_file("dummy", filename, material_, flags); + } + else { + Logger::LOG_WARNING << "Failed to auto-load geometry " << filename_ << ": Failed to extract filename and/or loading flags!" << std::endl; + } + } + else { + Logger::LOG_WARNING << "Failed to auto-load geometry " << filename_ << ": Type is not supported!" << std::endl; + } + } + else { + Logger::LOG_WARNING << "Failed to auto-load geometry " << filename_ << ": The name does not contain a type, file, id and flag parameter!" << std::endl; + } + } + } + + filename_changed_ = false; + } + + // The code below auto-loads a material if it's not already supported by + // the MaterialDatabase. It expects a material name like + // + // data/materials/Stones.gmd + + if (material_changed_) + { + if (material_ != "") + { + if (!MaterialDatabase::instance()->is_supported(material_)) + { + MaterialDatabase::instance()->load_material(material_); + } + } + + material_changed_ = false; + } + + GeometryNode::update_cache(); + } + //////////////////////////////////////////////////////////////////////////////// std::shared_ptr NURBSNode::copy() const { return std::make_shared(get_name(), filename_, material_, get_transform()); diff --git a/src/gua/scenegraph/Node.cpp b/src/gua/scenegraph/Node.cpp index f266bd5b4..eaea881d9 100644 --- a/src/gua/scenegraph/Node.cpp +++ b/src/gua/scenegraph/Node.cpp @@ -61,13 +61,15 @@ namespace gua { void Node::update_cache() { - if (self_dirty_) { - math::mat4 old_world_trans(world_transform_); - if (is_root()) { - world_transform_ = get_transform(); - } else { - world_transform_ = parent_->world_transform_ * get_transform(); - } + if (self_dirty_) + { + math::mat4 old_world_trans(world_transform_); + if (is_root()) { + world_transform_ = get_transform(); + } else { + world_transform_ = parent_->world_transform_ * get_transform(); + } + if (is_root()) { world_transform_ = get_transform(); } @@ -75,11 +77,10 @@ namespace gua { world_transform_ = parent_->world_transform_ * get_transform(); } - if (world_transform_ != old_world_trans) { - on_world_transform_changed.emit(world_transform_); - } + if (world_transform_ != old_world_trans) { + on_world_transform_changed.emit(world_transform_); + } - self_dirty_ = false; self_dirty_ = false; } @@ -358,6 +359,7 @@ namespace gua { //////////////////////////////////////////////////////////////////////////////// void Node::set_dirty() const { + self_dirty_ = true; set_children_dirty(); set_parent_dirty(); } @@ -377,11 +379,11 @@ namespace gua { if (!self_dirty_) { self_dirty_ = true; child_dirty_ = true; - - for (auto child : children_) { - child->set_children_dirty(); - } } + for (auto child : children_) { + child->set_children_dirty(); + } + } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/scenegraph/TriMeshNode.cpp b/src/gua/scenegraph/TriMeshNode.cpp index 6e9717ac9..58eb3eae7 100644 --- a/src/gua/scenegraph/TriMeshNode.cpp +++ b/src/gua/scenegraph/TriMeshNode.cpp @@ -230,15 +230,14 @@ namespace gua { { if (!MaterialDatabase::instance()->is_supported(material_)) { - auto mat = std::make_shared(material_, MaterialDescription(material_)); - MaterialDatabase::instance()->add(material_, mat); + MaterialDatabase::instance()->load_material(material_); } } material_changed_ = false; } - Node::update_cache(); + GeometryNode::update_cache(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/scenegraph/Video3DNode.cpp b/src/gua/scenegraph/Video3DNode.cpp index 6bf84fb14..70a58c330 100644 --- a/src/gua/scenegraph/Video3DNode.cpp +++ b/src/gua/scenegraph/Video3DNode.cpp @@ -25,7 +25,8 @@ // guacamole headers #include #include -#include +#include +#include #include #include #include @@ -47,17 +48,70 @@ namespace gua { math::vec3( 3.0, 2.5, 3.0)); } + ///////////////////////////////////////////////////////////////////////////// + void Video3DNode::update_bounding_box() const { //Logger::LOG_WARNING << "not implemented: Video3DNode::update_bounding_box()" << std::endl; } + ///////////////////////////////////////////////////////////////////////////// + void Video3DNode::ray_test_impl(RayNode const& ray, PickResult::Options options, Mask const& mask, std::set& hits) { Logger::LOG_WARNING << "not implemented: Video3DNode::ray_test_impl()" << std::endl; } + ///////////////////////////////////////////////////////////////////////////// + std::shared_ptr Video3DNode::copy() const { return std::make_shared(get_name(), filename_, material_, get_transform()); } + ///////////////////////////////////////////////////////////////////////////// + + /* virtual */ void Video3DNode::update_cache() + { + if (filename_changed_) + { + if (filename_ != "") + { + if (!GeometryDatabase::instance()->is_supported(filename_)) + { + Video3DLoader loader; + loader.create_geometry_from_file("dummy", filename_); + } + else { + Logger::LOG_WARNING << "Failed to auto-load geometry " << filename_ << ": Type is not supported!" << std::endl; + } + } + else { + Logger::LOG_WARNING << "Failed to auto-load geometry " << filename_ << ": The name does not contain a type, file, id and flag parameter!" << std::endl; + } + + filename_changed_ = false; + } + + // The code below auto-loads a material if it's not already supported by + // the MaterialDatabase. It expects a material name like + // + // data/materials/Stones.gmd + + if (material_changed_) + { + if (material_ != "") + { + if (!MaterialDatabase::instance()->is_supported(material_) && + material_ != Singleton::instance()->default_video_material_name() ) + { + auto mat = std::make_shared(material_, MaterialDescription(material_)); + MaterialDatabase::instance()->add(material_, mat); + } + } + + material_changed_ = false; + } + + Node::update_cache(); + } + }