diff --git a/src/main/java/com/replaymod/render/RenderSettings.java b/src/main/java/com/replaymod/render/RenderSettings.java index 6ff08de6..37977dda 100644 --- a/src/main/java/com/replaymod/render/RenderSettings.java +++ b/src/main/java/com/replaymod/render/RenderSettings.java @@ -1,6 +1,8 @@ package com.replaymod.render; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.Getter; import net.minecraft.client.resources.I18n; import org.lwjgl.util.ReadableColor; @@ -45,7 +47,7 @@ public class RenderSettings { } public String getValue() { - return "-y -f rawvideo -pix_fmt rgb24 -s %WIDTH%x%HEIGHT% -r %FPS% -i - " + preset; + return "-y -f rawvideo -pix_fmt rgb24 -s %WIDTH%x%HEIGHT% -r %FPS% -i - %FILTERS%" + preset; } public String getFileExtension() { @@ -64,6 +66,19 @@ public class RenderSettings { } } + @AllArgsConstructor + public enum AntiAliasing { + NONE(1), X2(2), X4(4), X8(8); + + @Getter + private final int factor; + + @Override + public String toString() { + return I18n.format("replaymod.gui.rendersettings.antialiasing." + name().toLowerCase()); + } + } + private final RenderMethod renderMethod; private final EncodingPreset encodingPreset; private final int videoWidth; @@ -78,9 +93,48 @@ public class RenderSettings { private final boolean stabilizeRoll; private final ReadableColor chromaKeyingColor; private final boolean inject360Metadata; + private final AntiAliasing antiAliasing; private final String exportCommand; private final String exportArguments; private final boolean highPerformance; + + /** + * @return the width of the output video during rendering, including the upscale for Anti-Aliasing. + */ + public int getVideoWidth() { + return videoWidth * antiAliasing.getFactor(); + } + + /** + * @return the height of the output video during rendering, including the upscale for Anti-Aliasing. + */ + public int getVideoHeight() { + return videoHeight * antiAliasing.getFactor(); + } + + /** + * @return the actual width of the output video. + */ + public int getTargetVideoWidth() { + return videoWidth; + } + + /** + * @return the actual height of the output video. + */ + public int getTargetVideoHeight() { + return videoHeight; + } + + public String getVideoFilters() { + if (antiAliasing == AntiAliasing.NONE) { + return ""; + } else { + double factor = 1.0 / antiAliasing.getFactor(); + return String.format("-vf scale=iw*%1$s:ih*%1$s ", factor); + } + } + } diff --git a/src/main/java/com/replaymod/render/VideoWriter.java b/src/main/java/com/replaymod/render/VideoWriter.java index 1e98ab37..29830bd7 100755 --- a/src/main/java/com/replaymod/render/VideoWriter.java +++ b/src/main/java/com/replaymod/render/VideoWriter.java @@ -43,7 +43,8 @@ public class VideoWriter implements FrameConsumer { .replace("%HEIGHT%", String.valueOf(settings.getVideoHeight())) .replace("%FPS%", String.valueOf(settings.getFramesPerSecond())) .replace("%FILENAME%", fileName) - .replace("%BITRATE%", String.valueOf(settings.getBitRate())); + .replace("%BITRATE%", String.valueOf(settings.getBitRate())) + .replace("%FILTERS%", settings.getVideoFilters()); String executable = settings.getExportCommand().isEmpty() ? "ffmpeg" : settings.getExportCommand(); System.out.println("Starting " + settings.getExportCommand() + " with args: " + commandArgs); diff --git a/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java b/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java index 247db259..98ca109c 100644 --- a/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java +++ b/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java @@ -149,13 +149,18 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { public final GuiCheckbox inject360Metadata = new GuiCheckbox() .setI18nLabel("replaymod.gui.rendersettings.360metadata"); + public final GuiDropdownMenu antiAliasingDropdown = new GuiDropdownMenu() + .setSize(200, 20).setValues(RenderSettings.AntiAliasing.values()).setSelected(RenderSettings.AntiAliasing.NONE); + public final GuiPanel advancedPanel = new GuiPanel().setLayout(new VerticalLayout().setSpacing(15)) .addElements(null, nametagCheckbox, new GuiPanel().setLayout( new GridLayout().setCellsEqualSize(false).setColumns(2).setSpacingX(5).setSpacingY(15)) .addElements(new GridLayout.Data(0, 0.5), new GuiLabel().setI18nText("replaymod.gui.rendersettings.stabilizecamera"), stabilizePanel, chromaKeyingCheckbox, chromaKeyingColor, - inject360Metadata)); + inject360Metadata, + new GuiLabel(), // to show the anti-aliasing options in a new line + new GuiLabel().setI18nText("replaymod.gui.rendersettings.antialiasing"), antiAliasingDropdown)); public final GuiTextField exportCommand = new GuiTextField().setI18nHint("replaymod.gui.rendersettings.command") .setSize(55, 20).setMaxLength(100); @@ -347,8 +352,8 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { public void load(RenderSettings settings) { renderMethodDropdown.setSelected(settings.getRenderMethod()); encodingPresetDropdown.setSelected(settings.getEncodingPreset()); - videoWidth.setValue(settings.getVideoWidth()); - videoHeight.setValue(settings.getVideoHeight()); + videoWidth.setValue(settings.getTargetVideoWidth()); + videoHeight.setValue(settings.getTargetVideoHeight()); frameRateSlider.setValue(settings.getFramesPerSecond() - 10); if (settings.getBitRate() % (1 << 20) == 0) { bitRateField.setValue(settings.getBitRate() >> 20); @@ -380,6 +385,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { chromaKeyingColor.setColor(settings.getChromaKeyingColor()); } inject360Metadata.setChecked(settings.isInject360Metadata()); + antiAliasingDropdown.setSelected(settings.getAntiAliasing()); exportCommand.setText(settings.getExportCommand()); exportArguments.setText(settings.getExportArguments()); @@ -401,6 +407,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { stabilizeRoll.isChecked() && (serialize || stabilizeRoll.isEnabled()), chromaKeyingCheckbox.isChecked() ? chromaKeyingColor.getColor() : null, inject360Metadata.isChecked() && (serialize || inject360Metadata.isEnabled()), + antiAliasingDropdown.getSelectedValue(), exportCommand.getText(), exportArguments.getText(), net.minecraft.client.gui.GuiScreen.isCtrlKeyDown() @@ -415,7 +422,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { private RenderSettings getDefaultRenderSettings() { return new RenderSettings(RenderSettings.RenderMethod.DEFAULT, RenderSettings.EncodingPreset.MP4_DEFAULT, 1920, 1080, 60, 10 << 20, null, - true, false, false, false, null, false, "", RenderSettings.EncodingPreset.MP4_DEFAULT.getValue(), false); + true, false, false, false, null, false, RenderSettings.AntiAliasing.NONE, "", RenderSettings.EncodingPreset.MP4_DEFAULT.getValue(), false); } @Override diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index ecdf54ef..772db299 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -424,6 +424,12 @@ replaymod.gui.rendersettings.presets.webm.custom=WEBM - Custom Bitrate replaymod.gui.rendersettings.presets.mkv.lossless=MKV - Lossless replaymod.gui.rendersettings.presets.png=PNG Sequence +replaymod.gui.rendersettings.antialiasing=Anti-Aliasing +replaymod.gui.rendersettings.antialiasing.none=None +replaymod.gui.rendersettings.antialiasing.x2=2x +replaymod.gui.rendersettings.antialiasing.x4=4x +replaymod.gui.rendersettings.antialiasing.x8=8x + #Rendering GUI replaymod.gui.rendering.title=Rendering Video replaymod.gui.rendering.pause=Pause Rendering