Implement Running Godot as Movie Writer

* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.

This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).

**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).

Usage:

$ godot --write-movie movie.avi [scene_file.tscn]

Missing:

* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
This commit is contained in:
reduz 2022-06-17 00:55:19 +02:00
parent 362f53ff02
commit 5786516d4d
38 changed files with 2427 additions and 30 deletions

View file

@ -1193,6 +1193,20 @@ void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::V
RSG::texture_storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
}
RID RendererViewport::viewport_find_from_screen_attachment(DisplayServer::WindowID p_id) const {
RID *rids = nullptr;
uint32_t rid_count = viewport_owner.get_rid_count();
rids = (RID *)alloca(sizeof(RID *) * rid_count);
viewport_owner.fill_owned_buffer(rids);
for (uint32_t i = 0; i < rid_count; i++) {
Viewport *viewport = viewport_owner.get_or_null(rids[i]);
if (viewport->viewport_to_screen == p_id) {
return rids[i];
}
}
return RID();
}
bool RendererViewport::free(RID p_rid) {
if (viewport_owner.owns(p_rid)) {
Viewport *viewport = viewport_owner.get_or_null(p_rid);

View file

@ -282,6 +282,8 @@ public:
void viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_over_size, RS::ViewportSDFScale p_scale);
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const;
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
void set_default_clear_color(const Color &p_color);

View file

@ -629,6 +629,7 @@ public:
FUNC2(viewport_set_measure_render_time, RID, bool)
FUNC1RC(double, viewport_get_measured_render_time_cpu, RID)
FUNC1RC(double, viewport_get_measured_render_time_gpu, RID)
FUNC1RC(RID, viewport_find_from_screen_attachment, DisplayServer::WindowID)
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)