]> git.tdb.fi Git - libs/gl.git/commitdiff
Modernize the demo and tool programs
authorMikko Rasa <tdb@tdb.fi>
Thu, 11 Jun 2020 15:07:38 +0000 (18:07 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 11 Jun 2020 19:20:57 +0000 (22:20 +0300)
demos/desertpillars.cpp
tools/viewer.cpp

index cb06cd000bc05f32f3cb446133c08a555362e4fb..bf62b7e32f6a9c37be256a6dcc07204f9c476df6 100644 (file)
@@ -12,7 +12,7 @@
 #include <msp/gl/instancescene.h>
 #include <msp/gl/light.h>
 #include <msp/gl/lighting.h>
-#include <msp/gl/material.h>
+#include <msp/gl/basicmaterial.h>
 #include <msp/gl/mesh.h>
 #include <msp/gl/meshbuilder.h>
 #include <msp/gl/object.h>
@@ -26,6 +26,7 @@
 #include <msp/gl/technique.h>
 #include <msp/gl/tests.h>
 #include <msp/gl/texturecube.h>
+#include <msp/gl/windowview.h>
 #include <msp/graphics/simplewindow.h>
 #include <msp/input/keyboard.h>
 #include <msp/input/keys.h>
@@ -44,7 +45,7 @@ including:
 - Shadow mapping
 - Environment mapped reflections
 - Skybox using a cube map texture
-- Nested scenes and pipelines
+- Effects with nested pipelines
 - Complex multitexturing
 - Shader-based deformations
 - Creating a normalmapped texture through rendering
@@ -112,20 +113,20 @@ private:
        GL::Technique ground_tech;
        ObjectData ground_data;
 
-       GL::Program pillar_shprog;
-       GL::Material pillar_material;
+       GL::BasicMaterial pillar_material;
        GL::Technique pillar_tech;
        std::vector<ObjectData> pillar_data;
        std::vector<GL::AnimatedObject *> pillars;
 
        GL::Program cube_shprog;
        GL::Program cube_shadow_shprog;
-       GL::Material cube_material;
+       GL::BasicMaterial cube_material;
        GL::Technique cube_tech;
        ObjectData cube_data;
        Cube *cube;
        GL::EnvironmentMap *env_cube;
 
+       GL::WindowView view;
        GL::Pipeline pipeline;
        GL::Camera camera;
        GL::SimpleScene sky_scene;
@@ -146,12 +147,11 @@ private:
        float cube_phase;
        bool cube_frozen;
 
-       static const char texture_vertex_src[];
-       static const char texture_fragment_src[];
-       static const char skybox_vertex_src[];
-       static const char skybox_fragment_src[];
-       static const char ground_variables[];
-       static const char cube_variables[];
+       static const char texture_src[];
+       static const char skybox_src[];
+       static const char ground_src[];
+       static const char cube_src[];
+       static const char cube_shadow_src_tail[];
        static const float cube_shapes[];
 
 public:
@@ -159,6 +159,7 @@ public:
        ~DesertPillars();
 
 private:
+       void setup_view();
        void create_pipeline();
        void create_skybox();
        static void create_skybox_face(GL::TextureCube &, GL::TextureCubeFace);
@@ -180,68 +181,79 @@ private:
        void key_press(unsigned);
 };
 
-const char DesertPillars::texture_vertex_src[] =
-       "#version 130\n"
-       "in vec3 vertex;\n"
-       "in vec3 normal;\n"
-       "in vec3 color;\n"
-       "out vec3 v_normal;\n"
-       "out vec3 v_color;\n"
+const char DesertPillars::texture_src[] =
+       "import msp_interface;\n"
+       "#pragma MSP stage(vertex)\n"
        "void main()\n"
        "{\n"
        "       gl_Position = vec4(vertex.xy*2.0-1.0, -vertex.z*2.0, 1.0);\n"
-       "       v_normal = normal;\n"
-       "       v_color = color.rgb;\n"
-       "}\n";
-
-const char DesertPillars::texture_fragment_src[] =
-       "#version 130\n"
-       "in vec3 v_normal;\n"
-       "in vec3 v_color;\n"
-       "out vec4 frag_color;\n"
-       "out vec4 frag_normal;\n"
+       "       passthrough;\n"
+       "}\n"
+       "#pragma MSP stage(fragment)\n"
+       "layout(location=1) out vec4 frag_normal;\n"
        "void main()\n"
        "{\n"
-       "       frag_color = vec4(v_color, 1.0);\n"
-       "       frag_normal = vec4(v_normal*0.5+0.5, 1.0);\n"
+       "       frag_color = color;\n"
+       "       frag_normal = vec4(normal*0.5+0.5, 1.0);\n"
        "}\n";
 
-const char DesertPillars::skybox_vertex_src[] =
-       "#version 130\n"
-       "uniform mat4 projection_matrix;\n"
-       "uniform mat4 eye_obj_matrix;\n"
-       "in vec3 vertex;\n"
-       "out vec3 v_texcoord;\n"
+const char DesertPillars::skybox_src[] =
+       "import msp_interface;\n"
+       "uniform samplerCube sky;\n"
+       "#pragma MSP stage(vertex)\n"
        "void main()\n"
        "{\n"
-       "       gl_Position = projection_matrix*vec4(mat3(eye_obj_matrix)*vertex, 1.0);\n"
-       "       v_texcoord = vertex;\n"
-       "}";
-
-const char DesertPillars::skybox_fragment_src[] =
-       "#version 130\n"
-       "uniform samplerCube sky;\n"
-       "in vec3 v_texcoord;\n"
-       "out vec4 frag_color;\n"
+       "       gl_Position = projection_matrix*vec4(mat3(eye_obj_matrix)*vertex.xyz, 1.0);\n"
+       "       passthrough;\n"
+       "}\n"
+       "#pragma MSP stage(fragment)\n"
        "void main()\n"
        "{\n"
-       "       frag_color = textureCube(sky, v_texcoord);\n"
-       "}";
+       "       frag_color = texture(sky, vertex.xyz);\n"
+       "}\n";
 
-const char DesertPillars::ground_variables[] =
+const char DesertPillars::ground_src[] =
+       "import phong;\n"
        "uniform sampler2D texture1;\n"
        "uniform sampler2D normalmap1;\n"
        "uniform sampler2D texture2;\n"
        "uniform sampler2D normalmap2;\n"
-       "attribute float ground_type;\n"
-       "fragment vec4 diffuse_sample = mix(texture2D(texture1, texture_coord*3.0), texture2D(texture2, texture_coord), ground_type);\n"
-       "fragment vec3 normal_sample = mix(texture2D(normalmap1, texture_coord*3.0).rgb, texture2D(normalmap2, texture_coord).rgb, ground_type);\n";
+       "const bool use_normal_map = true;\n"
+       "const bool use_shadow_map = true;\n"
+       "#pragma MSP stage(vertex)\n"
+       "layout(location=7) in float ground_type;\n"
+       "#pragma MSP stage(fragment)\n"
+       "vec4 get_diffuse_color()\n"
+       "{\n"
+       "       return mix(texture(texture1, texcoord.xy*3.0), texture(texture2, texcoord.xy), ground_type);\n"
+       "}\n"
+       "vec4 get_normal_sample()\n"
+       "{\n"
+       "       return mix(texture(normalmap1, texcoord.xy*3.0).rgb, texture(normalmap2, texcoord.xy).rgb, ground_type);\n"
+       "}\n";
 
-const char DesertPillars::cube_variables[] =
+const char DesertPillars::cube_src[] =
+       "import phong;\n"
+       "const bool use_specular = true;\n"
+       "const bool use_reflectivity = true;\n"
        "uniform float spherify;\n"
-       "attribute vec3 sphere_coord;\n"
-       "vertex vec3 eye_normal = eye_obj_normal_matrix*normalize(mix(normal, normalize(sphere_coord), spherify));\n"
-       "vertex vec4 eye_vertex = eye_obj_matrix*vec4(mix(vertex.xyz, sphere_coord, spherify), 1.0);\n";
+       "#pragma MSP stage(vertex)\n"
+       "layout(location=7) in vec3 sphere_coord;\n"
+       "vec4 transform_position(vec4 pos)\n"
+       "{\n"
+       "       return eye_obj_matrix*vec4(mix(vertex.xyz, sphere_coord, spherify), 1.0);\n"
+       "}\n"
+       "vec3 transform_normal(vec3 pos)\n"
+       "{\n"
+       "       return eye_obj_normal_matrix*normalize(mix(normal, normalize(sphere_coord), spherify));\n"
+       "}\n";
+
+const char DesertPillars::cube_shadow_src_tail[] =
+       "#pragma MSP stage(fragment)\n"
+       "void main()\n"
+       "{\n"
+       "       frag_color = vec4(1.0);\n"
+       "}\n";
 
 const float DesertPillars::cube_shapes[] = { -0.4, 0.5, 1.0, 0.3 };
 
@@ -271,8 +283,13 @@ DesertPillars::DesertPillars(int argc, char **argv):
        window(display, options.window_opts),
        gl_context(window),
        keyboard(window),
-       shadow_shprog(GL::ProgramBuilder::StandardFeatures()),
-       pipeline(window.get_width(), window.get_height()),
+       skybox_shprog(skybox_src),
+       shadow_shprog("occluder.glsl"),
+       ground_shprog(ground_src),
+       cube_shprog(cube_src),
+       cube_shadow_shprog(string(cube_src)+cube_shadow_src_tail),
+       view(window, gl_context),
+       pipeline(view),
        shadow_scene(2048, scene, light),
        bloom(window.get_width(), window.get_height()),
        env_pipeline(512, 512),
@@ -290,6 +307,7 @@ DesertPillars::DesertPillars(int argc, char **argv):
                window.show_cursor(false);
        keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &DesertPillars::key_press), false));
 
+       setup_view();
        create_pipeline();
        create_skybox();
        create_ground();
@@ -305,22 +323,24 @@ DesertPillars::~DesertPillars()
                delete *i;
 }
 
-void DesertPillars::create_pipeline()
+void DesertPillars::setup_view()
 {
-       pipeline.set_multisample(8);
-
-       camera.set_aspect(float(window.get_width())/window.get_height());
+       camera.set_aspect_ratio(float(window.get_width())/window.get_height());
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        camera.set_depth_clip(1, 50);
-       pipeline.set_camera(&camera);
+       view.set_camera(&camera);
+       view.set_content(&pipeline);
+}
+
+void DesertPillars::create_pipeline()
+{
+       pipeline.set_multisample(8);
 
        /* The shadow map is focused on the part of the scene that contains the
        pillars and the cube.  Making the ground cast shadows as well would result
        either in a very low spatial resolution of the shadow map, or ugly artifacts
        as the ground crosses the shadow map boundary. */
        shadow_scene.set_target(GL::Vector3(0, 0, 0), 10);
-       sky_scene.add(shadow_scene);
-       pipeline.add_renderable(sky_scene);
 
        // Put the sun pretty high in the sky
        light.set_position(GL::Vector4(0.5, -2, 3, 0));
@@ -328,9 +348,9 @@ void DesertPillars::create_pipeline()
        lighting.set_ambient(GL::Color(0.5));
 
        // The skybox is rendered first
-       pipeline.add_pass("sky");
+       pipeline.add_pass(0, sky_scene);
 
-       GL::Pipeline::Pass *pass = &pipeline.add_pass(0);
+       GL::Pipeline::Pass *pass = &pipeline.add_pass(0, shadow_scene);
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 
@@ -341,9 +361,8 @@ void DesertPillars::create_pipeline()
 
        /* Initialize a second pipeline to render the environment map.  It has the
        same renderables and passes, but no postprocessors or camera. */
-       env_pipeline.add_renderable(sky_scene);
-       env_pipeline.add_pass("sky");
-       pass = &env_pipeline.add_pass(0);
+       env_pipeline.add_pass(0, sky_scene);
+       pass = &env_pipeline.add_pass(0, shadow_scene);
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 }
@@ -356,13 +375,7 @@ void DesertPillars::create_skybox()
        for(unsigned i=0; i<6; ++i)
                create_skybox_face(skybox_tex, skybox_tex.enumerate_faces(i));
 
-       skybox_shprog.attach_shader_owned(new GL::VertexShader(skybox_vertex_src));
-       skybox_shprog.attach_shader_owned(new GL::FragmentShader(skybox_fragment_src));
-       skybox_shprog.bind_attribute(GL::VERTEX3, "vertex");
-       skybox_shprog.bind_fragment_data(0, "frag_color");
-       skybox_shprog.link();
-
-       GL::RenderPass &pass = skybox_tech.add_pass("sky");
+       GL::RenderPass &pass = skybox_tech.add_pass(0);
        pass.set_shader_program(&skybox_shprog, 0);
        pass.set_texture(0, &skybox_tex);
 
@@ -461,20 +474,14 @@ void DesertPillars::create_tiles_texture()
                        bld.end();
                }
 
-       GL::Program shprog(texture_vertex_src, texture_fragment_src);
-       shprog.bind_attribute(GL::VERTEX3, "vertex");
-       shprog.bind_attribute(GL::NORMAL3, "normal");
-       shprog.bind_attribute(GL::COLOR4_UBYTE, "color");
-       shprog.bind_fragment_data(0, "frag_color");
-       shprog.bind_fragment_data(1, "frag_normal");
-       shprog.link();
+       GL::Program shprog(texture_src);
 
        // Use an FBO to turn the geometry into a normalmapped texture
        GL::Framebuffer fbo;
        fbo.attach(GL::COLOR_ATTACHMENT0, tiles_texture);
        fbo.attach(GL::COLOR_ATTACHMENT1, tiles_normalmap);
        GL::Bind bind_fbo(fbo);
-       GL::Renderer renderer(0);
+       GL::Renderer renderer;
        renderer.set_shader_program(&shprog, 0);
        tiles.draw(renderer);
 }
@@ -487,11 +494,11 @@ void DesertPillars::create_sand_texture()
        sand_texture.storage(GL::RGB, width/16, height/16);
        sand_texture.set_min_filter(GL::LINEAR_MIPMAP_LINEAR);
        sand_texture.set_max_anisotropy(4);
-       sand_texture.set_generate_mipmap(true);
+       sand_texture.set_auto_generate_mipmap(true);
        sand_normalmap.storage(GL::RGB, width, height);
        sand_normalmap.set_min_filter(GL::LINEAR_MIPMAP_LINEAR);
        sand_normalmap.set_max_anisotropy(4);
-       sand_normalmap.set_generate_mipmap(true);
+       sand_normalmap.set_auto_generate_mipmap(true);
 
        unsigned char *pixels = new unsigned char[width*height*3];
        unsigned char *bump = new unsigned char[width*height];
@@ -573,16 +580,6 @@ void DesertPillars::create_ground()
        create_tiles_texture();
        create_sand_texture();
 
-       GL::ProgramBuilder::StandardFeatures features;
-       features.lighting = true;
-       features.shadow = true;
-       features.texture = true;
-       features.normal_map = true;
-       features.custom = ground_variables;
-       GL::ProgramBuilder(features).add_shaders(ground_shprog);
-       ground_shprog.bind_attribute(7, "ground_type");
-       ground_shprog.link();
-
        ground_shdata.uniform("texture1", 0);
        ground_shdata.uniform("normalmap1", 1);
        ground_shdata.uniform("texture2", 2);
@@ -662,18 +659,10 @@ void DesertPillars::create_pillars()
 {
        // The pillars are a matt off-white
        pillar_material.set_diffuse(GL::Color(0.9, 0.88, 0.8));
-       pillar_material.set_ambient(GL::Color(0.9, 0.88, 0.8));
-
-       GL::ProgramBuilder::StandardFeatures features;
-       features.lighting = true;
-       features.material = true;
-       features.shadow = true;
-       GL::ProgramBuilder(features).add_shaders(pillar_shprog);
-       pillar_shprog.link();
+       pillar_material.set_receive_shadows(true);
 
        GL::RenderPass *pass = &pillar_tech.add_pass(0);
        pass->set_material(&pillar_material);
-       pass->set_shader_program(&pillar_shprog, 0);
 
        pass = &pillar_tech.add_pass("shadow");
        pass->set_shader_program(&shadow_shprog, 0);
@@ -719,9 +708,9 @@ void DesertPillars::create_pillars()
                        }
 
                        // Create a square plinth and capitel
-                       bld.matrix() = GL::Matrix::translation(0, 0, 0.3);
+                       bld.set_matrix(GL::Matrix::translation(0, 0, 0.3));
                        GL::BoxBuilder(1.0, 1.0, 0.6).build(bld);
-                       bld.matrix() = GL::Matrix::translation(0, 0, height+0.8);
+                       bld.set_matrix(GL::Matrix::translation(0, 0, height+0.8));
                        GL::BoxBuilder(1.0, 1.0, 0.4).build(bld);
 
                        pd.object = new GL::Object(pd.mesh, &pillar_tech);
@@ -744,28 +733,10 @@ void DesertPillars::create_cube()
        /* The cube is bluish-gray, with a hard specular reflection to produce a
        sun-like spot */
        cube_material.set_diffuse(GL::Color(0.5, 0.5, 0.55));
-       cube_material.set_ambient(GL::Color(0.5, 0.5, 0.55));
        cube_material.set_specular(GL::Color(1.0));
        cube_material.set_shininess(120);
        cube_material.set_reflectivity(0.5);
 
-       // First create a simplified shader for rendering the shadow map
-       GL::ProgramBuilder::StandardFeatures features;
-       features.custom = cube_variables;
-       GL::ProgramBuilder(features).add_shaders(cube_shadow_shprog);
-       cube_shadow_shprog.bind_attribute(7, "sphere_coord");
-       cube_shadow_shprog.link();
-
-       // Then add the rest of the features for normal rendering
-       features.lighting = true;
-       features.specular = true;
-       features.material = true;
-       features.shadow = true;
-       features.reflection = true;
-       GL::ProgramBuilder(features).add_shaders(cube_shprog);
-       cube_shprog.bind_attribute(7, "sphere_coord");
-       cube_shprog.link();
-
        GL::RenderPass *pass = &cube_tech.add_pass(0);
        pass->set_material(&cube_material);
        pass->set_shader_program(&cube_shprog, 0);
@@ -888,9 +859,7 @@ void DesertPillars::tick()
        }
 
        display.tick();
-       GL::Framebuffer::system().clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
-       pipeline.render();
-       gl_context.swap_buffers();
+       view.render();
 }
 
 void DesertPillars::key_press(unsigned key)
index d2a384f4e0b2afc112afd7fe3ea62ac3da676237..a1853e922f19485097ee644e80900b76c9913b1f 100644 (file)
 #include <msp/gl/lighting.h>
 #include <msp/gl/mesh.h>
 #include <msp/gl/object.h>
+#include <msp/gl/pipeline.h>
 #include <msp/gl/renderer.h>
 #include <msp/gl/resources.h>
 #include <msp/gl/simplescene.h>
 #include <msp/gl/technique.h>
 #include <msp/gl/tests.h>
+#include <msp/gl/windowview.h>
 #include <msp/input/mouse.h>
 #include <msp/io/print.h>
 #include <msp/time/timestamp.h>
@@ -48,6 +50,8 @@ private:
        Graphics::SimpleGLWindow window;
        Input::Mouse mouse;
        Resources resources;
+       GL::WindowView view;
+       GL::Pipeline pipeline;
        GL::Renderable *renderable;
        GL::AnimatedObject *anim_object;
        GL::AnimationPlayer *anim_player;
@@ -86,6 +90,8 @@ private:
 Viewer::Viewer(int argc, char **argv):
        window(1024, 768, false),
        mouse(window),
+       view(window, window.get_gl_context()),
+       pipeline(view),
        renderable(0),
        anim_object(0),
        anim_player(0),
@@ -177,6 +183,14 @@ Viewer::Viewer(int argc, char **argv):
 
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        update_camera();
+
+       GL::Pipeline::Pass &pass = pipeline.add_pass(0, *renderable);
+       pass.set_lighting(&lighting);
+       pass.set_depth_test(&GL::DepthTest::lequal());
+       pass.set_blend(&GL::Blend::alpha());
+
+       view.set_content(&pipeline);
+       view.set_camera(&camera);
 }
 
 template<typename T>
@@ -219,16 +233,7 @@ void Viewer::tick()
        }
 
        window.tick();
-
-       GL::Framebuffer::system().clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
-
-       GL::Bind bind_depth(GL::DepthTest::lequal());
-       GL::Bind bind_blend(GL::Blend::alpha());
-       GL::Renderer renderer(&camera);
-       renderer.set_lighting(&lighting);
-       renderable->render(renderer);
-
-       window.swap_buffers();
+       view.render();
 }
 
 void Viewer::button_press(unsigned btn)