]> git.tdb.fi Git - libs/gl.git/blobdiff - demos/desertpillars.cpp
Rename Pipeline to Sequence
[libs/gl.git] / demos / desertpillars.cpp
index bf62b7e32f6a9c37be256a6dcc07204f9c476df6..d741beea5390b0eb8307fdb78d401fb47c62b314 100644 (file)
@@ -5,6 +5,7 @@
 #include <msp/gl/animatedobject.h>
 #include <msp/gl/bloom.h>
 #include <msp/gl/box.h>
+#include <msp/gl/colorcurve.h>
 #include <msp/gl/cylinder.h>
 #include <msp/gl/environmentmap.h>
 #include <msp/gl/framebuffer.h>
 #include <msp/gl/mesh.h>
 #include <msp/gl/meshbuilder.h>
 #include <msp/gl/object.h>
-#include <msp/gl/pipeline.h>
+#include <msp/gl/sequence.h>
 #include <msp/gl/program.h>
-#include <msp/gl/programbuilder.h>
 #include <msp/gl/renderer.h>
+#include <msp/gl/resources.h>
 #include <msp/gl/shader.h>
 #include <msp/gl/shadowmap.h>
 #include <msp/gl/simplescene.h>
@@ -45,7 +46,7 @@ including:
 - Shadow mapping
 - Environment mapped reflections
 - Skybox using a cube map texture
-- Effects with nested pipelines
+- Effects with nested sequences
 - Complex multitexturing
 - Shader-based deformations
 - Creating a normalmapped texture through rendering
@@ -96,13 +97,15 @@ private:
        Msp::Graphics::Window window;
        Msp::Graphics::GLContext gl_context;
        Msp::Input::Keyboard keyboard;
+       GL::Resources resources;
 
        GL::Program skybox_shprog;
        GL::Technique skybox_tech;
        GL::TextureCube skybox_tex;
+       GL::Sampler linear_clamped_sampler;
        ObjectData skybox_data;
 
-       GL::Program shadow_shprog;
+       const GL::Program &shadow_shprog;
 
        GL::Program ground_shprog;
        GL::ProgramData ground_shdata;
@@ -110,6 +113,8 @@ private:
        GL::Texture2D tiles_normalmap;
        GL::Texture2D sand_texture;
        GL::Texture2D sand_normalmap;
+       GL::Sampler linear_sampler;
+       GL::Sampler mipmap_sampler;
        GL::Technique ground_tech;
        ObjectData ground_data;
 
@@ -127,7 +132,7 @@ private:
        GL::EnvironmentMap *env_cube;
 
        GL::WindowView view;
-       GL::Pipeline pipeline;
+       GL::Sequence sequence;
        GL::Camera camera;
        GL::SimpleScene sky_scene;
        GL::InstanceScene scene;
@@ -135,8 +140,9 @@ private:
        GL::Light light;
        GL::ShadowMap shadow_scene;
        GL::Bloom bloom;
+       GL::ColorCurve colorcurve;
 
-       GL::Pipeline env_pipeline;
+       GL::Sequence env_sequence;
 
        Time::TimeStamp last_tick;
        float camera_angle;
@@ -160,7 +166,7 @@ public:
 
 private:
        void setup_view();
-       void create_pipeline();
+       void create_sequence();
        void create_skybox();
        static void create_skybox_face(GL::TextureCube &, GL::TextureCubeFace);
        void create_tiles_texture();
@@ -221,13 +227,17 @@ const char DesertPillars::ground_src[] =
        "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"
+       "layout(location=11) in float ground_type;\n"
+       "void custom_transform() override\n"
+       "{\n"
+       "       passthrough;\n"
+       "}\n"
        "#pragma MSP stage(fragment)\n"
-       "vec4 get_diffuse_color()\n"
+       "vec4 get_diffuse_color() override\n"
        "{\n"
        "       return mix(texture(texture1, texcoord.xy*3.0), texture(texture2, texcoord.xy), ground_type);\n"
        "}\n"
-       "vec4 get_normal_sample()\n"
+       "vec3 get_fragment_normal() override\n"
        "{\n"
        "       return mix(texture(normalmap1, texcoord.xy*3.0).rgb, texture(normalmap2, texcoord.xy).rgb, ground_type);\n"
        "}\n";
@@ -238,12 +248,12 @@ const char DesertPillars::cube_src[] =
        "const bool use_reflectivity = true;\n"
        "uniform float spherify;\n"
        "#pragma MSP stage(vertex)\n"
-       "layout(location=7) in vec3 sphere_coord;\n"
-       "vec4 transform_position(vec4 pos)\n"
+       "layout(location=11) in vec3 sphere_coord;\n"
+       "vec4 transform_position(vec4 pos) override\n"
        "{\n"
        "       return eye_obj_matrix*vec4(mix(vertex.xyz, sphere_coord, spherify), 1.0);\n"
        "}\n"
-       "vec3 transform_normal(vec3 pos)\n"
+       "vec3 transform_normal(vec3 pos) override\n"
        "{\n"
        "       return eye_obj_normal_matrix*normalize(mix(normal, normalize(sphere_coord), spherify));\n"
        "}\n";
@@ -284,15 +294,16 @@ DesertPillars::DesertPillars(int argc, char **argv):
        gl_context(window),
        keyboard(window),
        skybox_shprog(skybox_src),
-       shadow_shprog("occluder.glsl"),
+       shadow_shprog(resources.get<GL::Program>("_occluder.glsl.shader")),
        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),
+       sequence(view),
+       shadow_scene(resources, 2048, scene, light),
+       bloom(resources, window.get_width(), window.get_height()),
+       colorcurve(resources),
+       env_sequence(512, 512),
        camera_angle(0),
        camera_stopped(false),
        cube_angle(0),
@@ -308,7 +319,7 @@ DesertPillars::DesertPillars(int argc, char **argv):
        keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &DesertPillars::key_press), false));
 
        setup_view();
-       create_pipeline();
+       create_sequence();
        create_skybox();
        create_ground();
        create_pillars();
@@ -329,55 +340,63 @@ void DesertPillars::setup_view()
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        camera.set_depth_clip(1, 50);
        view.set_camera(&camera);
-       view.set_content(&pipeline);
+       view.set_content(&sequence);
 }
 
-void DesertPillars::create_pipeline()
+void DesertPillars::create_sequence()
 {
-       pipeline.set_multisample(8);
+       sequence.set_multisample(8);
+       sequence.set_hdr(true);
 
        /* 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);
+       shadow_scene.set_darkness(1);
 
        // Put the sun pretty high in the sky
+       light.set_diffuse(GL::Color(2.0));
        light.set_position(GL::Vector4(0.5, -2, 3, 0));
        lighting.attach(0, light);
-       lighting.set_ambient(GL::Color(0.5));
+       lighting.set_ambient(GL::Color(0.2));
 
        // The skybox is rendered first
-       pipeline.add_pass(0, sky_scene);
+       sequence.add_pass(0, sky_scene);
 
-       GL::Pipeline::Pass *pass = &pipeline.add_pass(0, shadow_scene);
+       GL::Sequence::Pass *pass = &sequence.add_pass(0, shadow_scene);
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 
        /* A bloom filter enhances the realism of bright surfaces, even if there
        isn't anything really glowy in the scene. */
        bloom.set_strength(0.3);
-       pipeline.add_postprocessor(bloom);
+       sequence.add_postprocessor(bloom);
 
-       /* Initialize a second pipeline to render the environment map.  It has the
+       /* Lighting calculations are best done in linear color space, so the final
+       image must be converted to srgb for display. */
+       colorcurve.set_srgb();
+       sequence.add_postprocessor(colorcurve);
+
+       /* Initialize a second sequence to render the environment map.  It has the
        same renderables and passes, but no postprocessors or camera. */
-       env_pipeline.add_pass(0, sky_scene);
-       pass = &env_pipeline.add_pass(0, shadow_scene);
+       env_sequence.add_pass(0, sky_scene);
+       pass = &env_sequence.add_pass(0, shadow_scene);
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 }
 
 void DesertPillars::create_skybox()
 {
-       skybox_tex.storage(GL::RGB, 128);
-       skybox_tex.set_min_filter(GL::LINEAR);
-       skybox_tex.set_wrap(GL::CLAMP_TO_EDGE);
+       skybox_tex.storage(GL::SRGB8, 128, 1);
+       linear_clamped_sampler.set_min_filter(GL::LINEAR);
+       linear_clamped_sampler.set_wrap(GL::CLAMP_TO_EDGE);
        for(unsigned i=0; i<6; ++i)
                create_skybox_face(skybox_tex, skybox_tex.enumerate_faces(i));
 
        GL::RenderPass &pass = skybox_tech.add_pass(0);
        pass.set_shader_program(&skybox_shprog, 0);
-       pass.set_texture(0, &skybox_tex);
+       pass.set_texture(0, &skybox_tex, &linear_clamped_sampler);
 
        // The shader will use the vertex coordinates to initialize texture coordinates as well
        skybox_data.mesh = new GL::Mesh(GL::VERTEX3);
@@ -411,7 +430,7 @@ void DesertPillars::create_skybox_face(GL::TextureCube &texture, GL::TextureCube
                                pixels[i+2] = 160;
                        }
                }
-       texture.image(face, 0, GL::RGB, GL::UNSIGNED_BYTE, pixels);
+       texture.image(face, 0, pixels);
        delete[] pixels;
 }
 
@@ -419,10 +438,9 @@ void DesertPillars::create_tiles_texture()
 {
        unsigned width = 256;
        unsigned height = 256;
-       tiles_texture.storage(GL::RGB, width, height);
-       tiles_texture.set_min_filter(GL::LINEAR);
-       tiles_normalmap.storage(GL::RGB, width, height);
-       tiles_normalmap.set_min_filter(GL::LINEAR);
+       tiles_texture.storage(GL::RGB8, width, height, 1);
+       tiles_normalmap.storage(GL::RGB8, width, height, 1);
+       linear_sampler.set_min_filter(GL::LINEAR);
 
        GL::Mesh tiles((GL::VERTEX3, GL::NORMAL3, GL::COLOR4_UBYTE));
 
@@ -437,6 +455,7 @@ void DesertPillars::create_tiles_texture()
                4, 4, 3, 3, 4, 1, 3, 2,
                2, 3, 2, 2, 3, 3, 3, 2 };
 
+       {
        GL::MeshBuilder bld(tiles);
 
        // Create a dark background
@@ -450,7 +469,7 @@ void DesertPillars::create_tiles_texture()
        bld.end();
 
        // Create the four tiles
-       bld.color(0.95f, 0.8f, 0.65f);
+       bld.color(GL::Color(0.95f, 0.8f, 0.65f).to_linear());
        for(unsigned i=0; i<2; ++i)
                for(unsigned j=0; j<2; ++j)
                {
@@ -473,6 +492,7 @@ void DesertPillars::create_tiles_texture()
                                bld.vertex(coords[i*4+order[32+l*2]], coords[j*4+order[32+l*2+1]], bevel);
                        bld.end();
                }
+       }
 
        GL::Program shprog(texture_src);
 
@@ -491,14 +511,12 @@ void DesertPillars::create_sand_texture()
        unsigned width = 512;
        unsigned height = 512;
 
-       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.storage(GL::SRGB8, width/16, height/16);
        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.storage(GL::RGB8, width, height);
        sand_normalmap.set_auto_generate_mipmap(true);
+       mipmap_sampler.set_min_filter(GL::LINEAR_MIPMAP_LINEAR);
+       mipmap_sampler.set_max_anisotropy(4);
 
        unsigned char *pixels = new unsigned char[width*height*3];
        unsigned char *bump = new unsigned char[width*height];
@@ -512,10 +530,10 @@ void DesertPillars::create_sand_texture()
                        pixels[i+2] = 160;
                        bump[x+y*width] = rand();
                }
-       sand_texture.image(0, GL::RGB, GL::UNSIGNED_BYTE, pixels);
+       sand_texture.image(0, pixels);
        gaussian_blur(bump, width, height);
        create_normalmap(bump, pixels, width, height, 4);
-       sand_normalmap.image(0, GL::RGB, GL::UNSIGNED_BYTE, pixels);
+       sand_normalmap.image(0, pixels);
        delete[] pixels;
        delete[] bump;
 }
@@ -587,15 +605,15 @@ void DesertPillars::create_ground()
 
        GL::RenderPass *pass = &ground_tech.add_pass(0);
        pass->set_shader_program(&ground_shprog, &ground_shdata);
-       pass->set_texture(0, &tiles_texture);
-       pass->set_texture(1, &tiles_normalmap);
-       pass->set_texture(2, &sand_texture);
-       pass->set_texture(3, &sand_normalmap);
+       pass->set_texture(0, &tiles_texture, &linear_sampler);
+       pass->set_texture(1, &tiles_normalmap, &linear_sampler);
+       pass->set_texture(2, &sand_texture, &mipmap_sampler);
+       pass->set_texture(3, &sand_normalmap, &mipmap_sampler);
 
        /* No shadow pass here; the ground only receives shadows, but doesn't cast
        them. */
 
-       GL::VertexFormat vfmt = (GL::VERTEX3, GL::NORMAL3, GL::TANGENT3, GL::BINORMAL3, GL::TEXCOORD2, GL::ATTRIB1,7);
+       GL::VertexFormat vfmt = (GL::VERTEX3, GL::NORMAL3, GL::TANGENT3, GL::BINORMAL3, GL::TEXCOORD2, GL::GENERIC1);
        ground_data.mesh = new GL::Mesh(vfmt);
 
        // Create a base grid
@@ -608,7 +626,7 @@ void DesertPillars::create_ground()
        unsigned tan = vfmt.offset(GL::TANGENT3);
        unsigned bin = vfmt.offset(GL::BINORMAL3);
        unsigned tex = vfmt.offset(GL::TEXCOORD2);
-       unsigned gt = vfmt.offset(GL::make_indexed_component(GL::ATTRIB1, 7));
+       unsigned gt = vfmt.offset(GL::GENERIC1);
        for(unsigned i=0; i<n_vertices; ++i)
        {
                float *v = ground_data.mesh->modify_vertex(i);
@@ -658,11 +676,11 @@ float DesertPillars::ground_height(float x, float y)
 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_diffuse(GL::Color(0.9, 0.89, 0.85).to_linear());
        pillar_material.set_receive_shadows(true);
 
        GL::RenderPass *pass = &pillar_tech.add_pass(0);
-       pass->set_material(&pillar_material);
+       pass->set_material(&pillar_material, &resources);
 
        pass = &pillar_tech.add_pass("shadow");
        pass->set_shader_program(&shadow_shprog, 0);
@@ -732,19 +750,19 @@ 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_diffuse(GL::Color(0.5, 0.5, 0.55).to_linear());
        cube_material.set_specular(GL::Color(1.0));
        cube_material.set_shininess(120);
        cube_material.set_reflectivity(0.5);
 
        GL::RenderPass *pass = &cube_tech.add_pass(0);
-       pass->set_material(&cube_material);
+       pass->set_material(&cube_material, &resources);
        pass->set_shader_program(&cube_shprog, 0);
 
        pass = &cube_tech.add_pass("shadow");
        pass->set_shader_program(&cube_shadow_shprog, 0);
 
-       cube_data.mesh = new GL::Mesh((GL::VERTEX3, GL::NORMAL3, GL::ATTRIB3,7));
+       cube_data.mesh = new GL::Mesh((GL::VERTEX3, GL::NORMAL3, GL::GENERIC3));
        GL::MeshBuilder bld(*cube_data.mesh);
        create_cube_face(bld, GL::Vector3(-1, -1, -1), GL::Vector3(2, 0, 0), GL::Vector3(0, 2, 0), 16);
        bld.offset(cube_data.mesh->get_n_vertices());
@@ -760,7 +778,7 @@ void DesertPillars::create_cube()
        cube_data.object = new GL::Object(cube_data.mesh, &cube_tech);
 
        cube = new Cube(*cube_data.object);
-       env_cube = new GL::EnvironmentMap(512, *cube, env_pipeline);
+       env_cube = new GL::EnvironmentMap(resources, 512, *cube, env_sequence);
        scene.add(*env_cube);
 }
 
@@ -786,7 +804,7 @@ void DesertPillars::create_cube_face(GL::MeshBuilder &bld, const GL::Vector3 &ba
 
                        l = sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
                        l /= 1.732;
-                       bld.attrib(7, v.x/l, v.y/l, v.z/l);
+                       bld.generic(0, v.x/l, v.y/l, v.z/l);
 
                        bld.vertex(v);
                }