X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=demos%2Fdesertpillars.cpp;h=bf62b7e32f6a9c37be256a6dcc07204f9c476df6;hb=3e9eb612a32ebe05030b934e0afb059f19cbb320;hp=61db0badcf8e0b1756f306ce4e1028bb77212f0b;hpb=7f08a54a61db86c60f06f4ddef529aa37e0d3d9c;p=libs%2Fgl.git diff --git a/demos/desertpillars.cpp b/demos/desertpillars.cpp index 61db0bad..bf62b7e3 100644 --- a/demos/desertpillars.cpp +++ b/demos/desertpillars.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,11 +26,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include using namespace std; @@ -43,8 +44,8 @@ including: - Creating a mesh and then modifying it - Shadow mapping - Environment mapped reflections -- Skybox -- Nested scenes and pipelines +- Skybox using a cube map texture +- Effects with nested pipelines - Complex multitexturing - Shader-based deformations - Creating a normalmapped texture through rendering @@ -112,21 +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 pillar_data; std::vector pillars; - GL::VertexShader cube_transform; 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; @@ -147,13 +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_transform_src[]; - static const char ground_colorify_src[]; - static const char cube_transform_src[]; + 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: @@ -161,6 +159,7 @@ public: ~DesertPillars(); private: + void setup_view(); void create_pipeline(); void create_skybox(); static void create_skybox_face(GL::TextureCube &, GL::TextureCubeFace); @@ -182,86 +181,84 @@ private: void key_press(unsigned); }; -const char DesertPillars::texture_vertex_src[] = - "varying vec3 v_normal;\n" - "varying 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(gl_Vertex.xy*2.0-1.0, -gl_Vertex.z*2.0, 1.0);\n" - " v_normal = gl_Normal;\n" - " v_color = gl_Color.rgb;\n" - "}\n"; - -const char DesertPillars::texture_fragment_src[] = - "varying vec3 v_normal;\n" - "varying vec3 v_color;\n" + " gl_Position = vec4(vertex.xy*2.0-1.0, -vertex.z*2.0, 1.0);\n" + " passthrough;\n" + "}\n" + "#pragma MSP stage(fragment)\n" + "layout(location=1) out vec4 frag_normal;\n" "void main()\n" "{\n" - " gl_FragData[0] = vec4(v_color, 1.0);\n" - " gl_FragData[1] = 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[] = - "varying vec3 v_texcoord;\n" - "void main()\n" - "{\n" - " gl_Position = gl_ProjectionMatrix*vec4(mat3(gl_ModelViewMatrix)*gl_Vertex.xyz, 1.0);\n" - " v_texcoord = gl_Vertex;\n" - "}"; - -const char DesertPillars::skybox_fragment_src[] = +const char DesertPillars::skybox_src[] = + "import msp_interface;\n" "uniform samplerCube sky;\n" - "varying vec3 v_texcoord;\n" + "#pragma MSP stage(vertex)\n" "void main()\n" "{\n" - " gl_FragColor = textureCube(sky, v_texcoord);\n" - "}"; - -// This exists only to transfer the ground type to fragment shader -const char DesertPillars::ground_transform_src[] = - "attribute float ground_type;\n" - "varying float v_ground_type;\n" - "vec4 transform_vertex(vec4 vertex)\n" - "{\n" - " v_ground_type = ground_type;\n" - " return gl_ModelViewMatrix*vertex;\n" + " gl_Position = projection_matrix*vec4(mat3(eye_obj_matrix)*vertex.xyz, 1.0);\n" + " passthrough;\n" "}\n" - "vec3 transform_normal(vec3 normal)\n" + "#pragma MSP stage(fragment)\n" + "void main()\n" "{\n" - " return gl_NormalMatrix*normal;\n" + " frag_color = texture(sky, vertex.xyz);\n" "}\n"; -const char DesertPillars::ground_colorify_src[] = +const char DesertPillars::ground_src[] = + "import phong;\n" "uniform sampler2D texture1;\n" "uniform sampler2D normalmap1;\n" "uniform sampler2D texture2;\n" "uniform sampler2D normalmap2;\n" - "varying float v_ground_type;\n" - "vec4 sample_texture(vec2 coord)\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(texture2D(texture1, coord*3), texture2D(texture2, coord), v_ground_type);\n" + " return mix(texture(texture1, texcoord.xy*3.0), texture(texture2, texcoord.xy), ground_type);\n" "}\n" - "vec3 sample_normalmap(vec2 coord)\n" + "vec4 get_normal_sample()\n" "{\n" - " return mix(texture2D(normalmap1, coord*3), texture2D(normalmap2, coord), v_ground_type);\n" + " return mix(texture(normalmap1, texcoord.xy*3.0).rgb, texture(normalmap2, texcoord.xy).rgb, ground_type);\n" "}\n"; -const char DesertPillars::cube_transform_src[] = +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" - "vec4 transform_vertex(vec4 vertex)\n" + "#pragma MSP stage(vertex)\n" + "layout(location=7) in vec3 sphere_coord;\n" + "vec4 transform_position(vec4 pos)\n" "{\n" - " return gl_ModelViewMatrix*vec4(mix(vertex, sphere_coord, spherify), 1.0);\n" + " return eye_obj_matrix*vec4(mix(vertex.xyz, sphere_coord, spherify), 1.0);\n" "}\n" - "vec3 transform_normal(vec3 normal)\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" - " return gl_NormalMatrix*normalize(mix(normal, normalize(sphere_coord), spherify));\n" + " frag_color = vec4(1.0);\n" "}\n"; const float DesertPillars::cube_shapes[] = { -0.4, 0.5, 1.0, 0.3 }; -DesertPillars::Options::Options(const Graphics::Display &display, int argc, char **argv) +DesertPillars::Options::Options(const Graphics::Display &dpy, int argc, char **argv) { GetOpt getopt; getopt.add_option('f', "fullscreen", window_opts.fullscreen, GetOpt::NO_ARG).set_help("Run in fullscreen mode"); @@ -269,7 +266,7 @@ DesertPillars::Options::Options(const Graphics::Display &display, int argc, char if(window_opts.fullscreen) { - const Graphics::VideoMode &mode = display.get_desktop_mode(); + const Graphics::VideoMode &mode = dpy.get_desktop_mode(); window_opts.width = mode.width; window_opts.height = mode.height; } @@ -286,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), @@ -303,8 +305,9 @@ DesertPillars::DesertPillars(int argc, char **argv): window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &DesertPillars::exit), 0)); if(options.window_opts.fullscreen) window.show_cursor(false); - keyboard.signal_button_press.connect(sigc::mem_fun(this, &DesertPillars::key_press)); + keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &DesertPillars::key_press), false)); + setup_view(); create_pipeline(); create_skybox(); create_ground(); @@ -320,23 +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); - shadow_scene.set_texture_unit(5); - 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)); @@ -344,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()); @@ -357,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()); } @@ -372,11 +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.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); @@ -475,14 +474,14 @@ void DesertPillars::create_tiles_texture() bld.end(); } - GL::Program shprog(texture_vertex_src, texture_fragment_src); + 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); } @@ -495,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]; @@ -581,19 +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.normalmap = true; - features.transform = true; - features.colorify = true; - GL::ProgramBuilder(features).add_shaders(ground_shprog); - ground_shprog.attach_shader_owned(new GL::VertexShader(ground_transform_src)); - ground_shprog.attach_shader_owned(new GL::FragmentShader(ground_colorify_src)); - 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); @@ -673,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); @@ -730,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); @@ -755,31 +733,9 @@ 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(150); - - cube_transform.source(cube_transform_src); - cube_transform.compile(); - - // First create a simplified shader for rendering the shadow map - GL::ProgramBuilder::StandardFeatures features; - features.transform = true; - GL::ProgramBuilder(features).add_shaders(cube_shadow_shprog); - cube_shadow_shprog.attach_shader(cube_transform); - 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.attach_shader(cube_transform); - cube_shprog.bind_attribute(7, "sphere_coord"); - cube_shprog.link(); + cube_material.set_shininess(120); + cube_material.set_reflectivity(0.5); GL::RenderPass *pass = &cube_tech.add_pass(0); pass->set_material(&cube_material); @@ -903,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) @@ -935,9 +889,7 @@ DesertPillars::ObjectData::~ObjectData() DesertPillars::Cube::Cube(const GL::Object &obj): GL::AnimatedObject(obj) -{ - shdata.uniform("reflectivity", 0.5f); -} +{ } void DesertPillars::Cube::set_spherify(float s) {