Hey all, I'm doing something which I figure should be very simple and have basically 0 cost, though I don't really have good heuristics for what is and what is not expensive when it comes to rendering so I figured I'd run it by here and see if I'm doing something completely ass-backwards.
Basically, I'm doing a roguelike thingy and have implemented FOV. I want to render this FOV as an overlay on top of my existing sprites. It is no issue creating this image, but when rendering it it feels like it heats up my computer more than neccesary. I make a very small image and then scale it up to my grid size (which is 24 pixels) so the image doesn't end up being very big at all. This is the code I have right now:
fn player_sight_render_visibility(
mut commands: Commands,
window: Single<&Window>,
player: Single<(Entity, &Sight, Ref<Position>), With<Player>>,
tiles: Res<BlockedTiles>,
settings: Res<GameSettings>,
camera: Single<(&OrthographicProjection, &GlobalTransform, Ref<Transform>), (With<Camera2d>)>,
overlay: Single<Entity, With<Overlay>>,
mut images: ResMut<Assets<Image>>,
) {
let (player_ent, sight_data, ref player_pos) = *player;
let (projection, camera_transform, ref transform) = *camera;
if !transform.is_changed() && !player_pos.is_changed() {
return;
}
eprintln!("creating new shadow image");
let camera_pos = camera_transform.translation().xy();
let (cam_x, cam_y) = translate_camera_position(&*settings, camera_pos.x, camera_pos.y);
let (window_w, window_h) = window.size().into();
let (window_w,window_h) = translate_camera_position(&*settings, window_w, window_h);
let buffer = ImageBuffer::from_fn(window_w as u32, window_h as u32, |x,y| {
let pos = Position::new(cam_x - window_w / 2 + x as i32, cam_y + window_h / 2 - y as i32);
if sight_data.visible_tiles.contains(&pos) {
LumaA([0f32, 0.])
} else {
LumaA([0f32, 0.5])
}
});
let mut image = Image::from_dynamic(DynamicImage::from(buffer), false, RenderAssetUsages::RENDER_WORLD);
image.sampler = ImageSampler::nearest();
let img_handle = images.add(image);
let mut overlay_sprite = Sprite::from_image(img_handle);
overlay_sprite.anchor = Anchor::TopLeft;
let k = settings.grid_size as f32;
commands.entity(*overlay).insert((
overlay_sprite,
Transform::from_scale(Vec3::new(k, k, 1.0))
.with_translation(Vec3::new(camera_pos.x - window.size().x / 2., camera_pos.y + window.size().y / 2., 0.0))
));
}
is this just inherently a very inefficient way of doing things? is there any other method I should use? It's not like my computer is burning up by any means but the GPU still gets pretty active whereas rendering just my other small sprites seems to be pretty much "free".