Exemple #1
0
/* main */
int
main ()
{
  /* initialize the corner info */
  while (1)
    {				/* loop is executed forever */
      int range;		/* range to target */
      int hit;			/* check for targets in range */
      int dir, sc;		/* scan direction */
      int d;			/* last damage check */

      new_corner ();		/* start at a random corner */
      d = damage ();		/* get current damage */

      /* scan around sc.  */
      sc = plot_course (500, 500);
      dir = sc - 46;
      hit = 0;
      do
	{
	  dir += 2;
	  if (dir >= sc + 45)	/* at end of 90 degrees range...  */
	    {
	      if (!hit)		/* move if we hit */
		break;
	      dir = sc - 45;	/* ... or restart */
	    }

	  range = scan (dir, 1);	/* look at a direction */

	  /* keep firing while in range, tolerating several hits */
	  while (range <= 700 && range > 0 && damage () <= d + 15)
	    {
	      hit = 1;
	      cannon (dir, range);	/* fire! */
	      range = scan (dir, 1);	/* check target again */
	    }

	  if (hit)
	    {
	      dir = MAX (dir - 10, sc - 45);	/* back up scan after attack */
	      hit = 0;
	    }
	}
      while (d == damage ());
    }
}
Exemple #2
0
void ShadowMap::render_cascaded(RenderContext const& ctx,
              SceneGraph const& scene_graph,
              math::vec3 const& center_of_interest,
              Frustum const& scene_frustum,
              Camera const& scene_camera,
              math::mat4 const& transform,
              unsigned map_size, float split_0,
              float split_1, float split_2,
              float split_3, float split_4,
              float near_clipping_in_sun_direction) {

  update_members(ctx, map_size*2);
  projection_view_matrices_ = std::vector<math::mat4>(4);

  buffer_->bind(ctx);
  buffer_->clear_depth_stencil_buffer(ctx);

  ctx.render_context->set_depth_stencil_state(depth_stencil_state_);
  ctx.render_context->set_rasterizer_state(rasterizer_state_);

  std::vector<float> splits({
    split_0, split_1, split_2, split_3, split_4
  });

  if (pipeline_->config.near_clip() > split_0 || pipeline_->config.far_clip() < split_4) {
    Logger::LOG_WARNING << "Splits of cascaded shadow maps are not inside clipping range! Fallback to equidistant splits used." << std::endl;
    float clipping_range(pipeline_->config.far_clip() - pipeline_->config.near_clip());
    splits = {
      pipeline_->config.near_clip(),
      pipeline_->config.near_clip() + clipping_range * 0.25f,
      pipeline_->config.near_clip() + clipping_range * 0.5f,
      pipeline_->config.near_clip() + clipping_range * 0.75f,
      pipeline_->config.far_clip()
    };
  }

  for (int y(0); y<2; ++y) {
    for (int x(0); x<2; ++x) {

      int cascade(y*2 + x);

      // render each cascade to a quarter of the shadow map
      ctx.render_context->set_viewport(scm::gl::viewport(
          math::vec2(x * map_size, y * map_size),
          math::vec2(map_size, map_size)));

      // set clipping of camera frustum according to current cascade
      Frustum cropped_frustum(Frustum::perspective(
        scene_frustum.get_camera_transform(),
        scene_frustum.get_screen_transform(),
        splits[cascade], splits[cascade+1]
      ));

      // transform cropped frustum tu sun space and calculate radius and bbox
      // of transformed frustum
      auto cropped_frustum_corners(cropped_frustum.get_corners());
      math::BoundingBox<math::vec3> extends_in_sun_space;
      float radius_in_sun_space = 0;
      std::vector<math::vec3> corners_in_sun_space;
      math::vec3 center_in_sun_space(0, 0, 0);

      auto inverse_sun_transform(scm::math::inverse(transform));
      for (auto const& corner: cropped_frustum_corners) {
        math::vec3 new_corner(inverse_sun_transform * corner);
        center_in_sun_space += new_corner/8;
        corners_in_sun_space.push_back(new_corner);
        extends_in_sun_space.expandBy(new_corner);
      }

      for (auto const& corner: corners_in_sun_space) {
        float radius = scm::math::length(corner-center_in_sun_space);
        if (radius > radius_in_sun_space)
          radius_in_sun_space = radius;
      }

      // center of front plane of frustum
      auto center(math::vec3((extends_in_sun_space.min[0] + extends_in_sun_space.max[0])/2,
                             (extends_in_sun_space.min[1] + extends_in_sun_space.max[1])/2,
                              extends_in_sun_space.max[2] + near_clipping_in_sun_direction));

      // eliminate sub-pixel movement
      float tex_coord_x = center.x * map_size / radius_in_sun_space / 2;
      float tex_coord_y = center.y * map_size / radius_in_sun_space / 2;

      float tex_coord_rounded_x = round(tex_coord_x);
      float tex_coord_rounded_y = round(tex_coord_y);

      float dx = tex_coord_rounded_x - tex_coord_x;
      float dy = tex_coord_rounded_y - tex_coord_y;

      dx /= map_size / radius_in_sun_space / 2;
      dy /= map_size / radius_in_sun_space / 2;

      center.x += dx;
      center.y += dy;

      // calculate transformation of shadow screen
      auto screen_in_sun_space(scm::math::make_translation(center) * scm::math::make_scale(radius_in_sun_space*2, radius_in_sun_space*2, 1.0f));
      auto sun_screen_transform(transform * screen_in_sun_space);

      // calculate transformation of shadow eye
      auto sun_eye_transform(scm::math::make_translation(sun_screen_transform.column(3)[0], sun_screen_transform.column(3)[1], sun_screen_transform.column(3)[2]));
      auto sun_eye_depth(transform * math::vec4(0, 0, extends_in_sun_space.max[2] - extends_in_sun_space.min[2] + near_clipping_in_sun_direction, 0.0f));

      auto shadow_frustum(
        Frustum::orthographic(
          sun_eye_transform,
          sun_screen_transform,
          0,
          scm::math::length(sun_eye_depth)
        )
      );

      // render geometries
      render_geometry(ctx, scene_graph, center_of_interest, shadow_frustum, scene_camera, cascade, map_size);
    }
  }

  ctx.render_context->reset_state_objects();

  buffer_->unbind(ctx);

}