Stop assuming that our render pipeline will only process RGB frames

For one, we have already switched to RGBA some time ago, so the name was
technically incorrect already.
But the main reason is that we'll want to use them for depth maps as well (and
potentially maybe even for HDR images if that's possible with canvas?).
This commit is contained in:
Jonas Herzig
2020-10-03 14:41:08 +02:00
parent 4c4c052d8a
commit aee486c4f3
19 changed files with 165 additions and 136 deletions

View File

@@ -4,7 +4,7 @@ import com.replaymod.core.ReplayMod;
import com.replaymod.core.utils.Utils;
import com.replaymod.core.versions.MCVer;
import com.replaymod.extras.ReplayModExtras;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.rendering.FrameConsumer;
import com.replaymod.replay.ReplayModReplay;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
@@ -14,7 +14,7 @@ import net.minecraft.util.crash.CrashReport;
import java.io.File;
import java.io.IOException;
public class ScreenshotWriter implements FrameConsumer<RGBFrame> {
public class ScreenshotWriter implements FrameConsumer<BitmapFrame> {
private final File outputFile;
@@ -23,7 +23,7 @@ public class ScreenshotWriter implements FrameConsumer<RGBFrame> {
}
@Override
public void consume(RGBFrame frame) {
public void consume(BitmapFrame frame) {
// skip the first frame, in which not all chunks are properly loaded
if (frame.getFrameId() == 0) return;

View File

@@ -1,7 +1,7 @@
package com.replaymod.render;
import com.replaymod.core.versions.MCVer;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.rendering.FrameConsumer;
import com.replaymod.render.rendering.VideoRenderer;
import com.replaymod.render.utils.ByteBufferPool;
@@ -26,7 +26,7 @@ import java.util.concurrent.TimeUnit;
import static com.replaymod.render.ReplayModRender.LOGGER;
import static org.apache.commons.lang3.Validate.isTrue;
public class VideoWriter implements FrameConsumer<RGBFrame> {
public class VideoWriter implements FrameConsumer<BitmapFrame> {
private final VideoRenderer renderer;
private final RenderSettings settings;
@@ -103,7 +103,7 @@ public class VideoWriter implements FrameConsumer<RGBFrame> {
}
@Override
public void consume(RGBFrame frame) {
public void consume(BitmapFrame frame) {
try {
checkSize(frame.getSize());
channel.write(frame.getByteBuffer());

View File

@@ -3,14 +3,14 @@ package com.replaymod.render.blend;
import com.replaymod.core.versions.MCVer;
import com.replaymod.render.capturer.RenderInfo;
import com.replaymod.render.capturer.WorldRenderer;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.rendering.FrameCapturer;
import com.replaymod.render.utils.ByteBufferPool;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import java.io.IOException;
public class BlendFrameCapturer implements FrameCapturer<RGBFrame> {
public class BlendFrameCapturer implements FrameCapturer<BitmapFrame> {
protected final WorldRenderer worldRenderer;
protected final RenderInfo renderInfo;
protected int framesDone;
@@ -26,7 +26,7 @@ public class BlendFrameCapturer implements FrameCapturer<RGBFrame> {
}
@Override
public RGBFrame process() {
public BitmapFrame process() {
if (framesDone == 0) {
BlendState.getState().setup();
}
@@ -37,7 +37,7 @@ public class BlendFrameCapturer implements FrameCapturer<RGBFrame> {
worldRenderer.renderWorld(MCVer.getRenderPartialTicks(), null);
BlendState.getState().postFrame(framesDone);
return new RGBFrame(framesDone++, new Dimension(0, 0), ByteBufferPool.allocate(0));
return new BitmapFrame(framesDone++, new Dimension(0, 0), 0, ByteBufferPool.allocate(0));
}
@Override

View File

@@ -53,7 +53,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
pboBuffer.limit(pboBuffer.position() + frameBufferSize);
frameBuffer.put(pboBuffer);
frameBuffer.rewind();
frames[i] = new OpenGlFrame(framesDone - 2, frameSize, frameBuffer);
frames[i] = new OpenGlFrame(framesDone - 2, frameSize, 4, frameBuffer);
}
pbo.unmap();

View File

@@ -112,7 +112,7 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
frameBuffer().endWrite();
buffer.rewind();
return new OpenGlFrame(frameId, new Dimension(getFrameWidth(), getFrameHeight()), buffer);
return new OpenGlFrame(frameId, new Dimension(getFrameWidth(), getFrameHeight()), 4, buffer);
}
protected void resize(int width, int height) {

View File

@@ -47,7 +47,7 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer<OpenGlFram
buffer.rewind();
pbo.unmap();
pbo.unbind();
frame = new OpenGlFrame(framesDone - 2, frameSize, buffer);
frame = new OpenGlFrame(framesDone - 2, frameSize, 4, buffer);
}
if (framesDone < renderInfo.getTotalFrames()) {

View File

@@ -6,19 +6,19 @@ import org.apache.commons.lang3.Validate;
import java.nio.ByteBuffer;
public class RGBFrame implements Frame {
public class BitmapFrame implements Frame {
private final int frameId;
private final ReadableDimension size;
private final int bytesPerPixel;
private final ByteBuffer byteBuffer;
public RGBFrame(int frameId, ReadableDimension size, ByteBuffer byteBuffer) {
Validate.isTrue(size.getWidth() * size.getHeight() * 4 == byteBuffer.remaining(),
public BitmapFrame(int frameId, ReadableDimension size, int bytesPerPixel, ByteBuffer byteBuffer) {
Validate.isTrue(size.getWidth() * size.getHeight() * bytesPerPixel == byteBuffer.remaining(),
"Buffer size is %d (cap: %d) but should be %d",
byteBuffer.remaining(), byteBuffer.capacity(), size.getWidth() * size.getHeight() * 4);
byteBuffer.remaining(), byteBuffer.capacity(), size.getWidth() * size.getHeight() * bytesPerPixel);
this.frameId = frameId;
this.size = size;
this.bytesPerPixel = bytesPerPixel;
this.byteBuffer = byteBuffer;
}
@@ -30,6 +30,10 @@ public class RGBFrame implements Frame {
return this.size;
}
public int getBytesPerPixel() {
return bytesPerPixel;
}
public ByteBuffer getByteBuffer() {
return this.byteBuffer;
}

View File

@@ -7,14 +7,14 @@ import java.nio.ByteBuffer;
public class OpenGlFrame implements Frame {
private final int frameId;
private final ReadableDimension size;
private final int bytesPerPixel;
private final ByteBuffer byteBuffer;
public OpenGlFrame(int frameId, ReadableDimension size, ByteBuffer byteBuffer) {
public OpenGlFrame(int frameId, ReadableDimension size, int bytesPerPixel, ByteBuffer byteBuffer) {
this.frameId = frameId;
this.size = size;
this.bytesPerPixel = bytesPerPixel;
this.byteBuffer = byteBuffer;
}
@@ -26,6 +26,10 @@ public class OpenGlFrame implements Frame {
return this.size;
}
public int getBytesPerPixel() {
return bytesPerPixel;
}
public ByteBuffer getByteBuffer() {
return this.byteBuffer;
}

View File

@@ -1,7 +1,7 @@
package com.replaymod.render.gui;
import com.replaymod.core.utils.Utils;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.rendering.VideoRenderer;
import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo;
@@ -265,7 +265,7 @@ public class GuiVideoRenderer extends GuiScreen implements Tickable {
guiRenderer.drawTexturedRect(x, y, 0, 0, width, height, videoWidth, videoHeight, videoWidth, videoHeight);
}
public void updatePreview(RGBFrame frame) {
public void updatePreview(BitmapFrame frame) {
if (previewCheckbox.isChecked() && previewTexture != null) {
ByteBuffer buffer = frame.getByteBuffer();
buffer.mark();

View File

@@ -0,0 +1,35 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.CubicOpenGlFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.utils.ByteBufferPool;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import java.nio.ByteBuffer;
import static com.replaymod.render.utils.Utils.openGlBytesToBitmap;
public class CubicToBitmapProcessor extends AbstractFrameProcessor<CubicOpenGlFrame, BitmapFrame> {
@Override
public BitmapFrame process(CubicOpenGlFrame rawFrame) {
int size = rawFrame.getLeft().getSize().getWidth();
int bpp = rawFrame.getLeft().getBytesPerPixel();
int width = size * 4;
int height = size * 3;
ByteBuffer result = ByteBufferPool.allocate(width * height * bpp);
openGlBytesToBitmap(rawFrame.getLeft(), 0, size, result, width);
openGlBytesToBitmap(rawFrame.getFront(), size, size, result, width);
openGlBytesToBitmap(rawFrame.getRight(), size * 2, size, result, width);
openGlBytesToBitmap(rawFrame.getBack(), size * 3, size, result, width);
openGlBytesToBitmap(rawFrame.getTop(), size, 0, result, width);
openGlBytesToBitmap(rawFrame.getBottom(), size, size * 2, result, width);
ByteBufferPool.release(rawFrame.getLeft().getByteBuffer());
ByteBufferPool.release(rawFrame.getRight().getByteBuffer());
ByteBufferPool.release(rawFrame.getFront().getByteBuffer());
ByteBufferPool.release(rawFrame.getBack().getByteBuffer());
ByteBufferPool.release(rawFrame.getTop().getByteBuffer());
ByteBufferPool.release(rawFrame.getBottom().getByteBuffer());
return new BitmapFrame(rawFrame.getFrameId(), new Dimension(width, height), bpp, result);
}
}

View File

@@ -1,33 +0,0 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.CubicOpenGlFrame;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.utils.ByteBufferPool;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import java.nio.ByteBuffer;
import static com.replaymod.render.utils.Utils.openGlBytesToRBG;
public class CubicToRGBProcessor extends AbstractFrameProcessor<CubicOpenGlFrame, RGBFrame> {
@Override
public RGBFrame process(CubicOpenGlFrame rawFrame) {
int size = rawFrame.getLeft().getSize().getWidth();
int width = size * 4;
int height = size * 3;
ByteBuffer result = ByteBufferPool.allocate(width * height * 4);
openGlBytesToRBG(rawFrame.getLeft().getByteBuffer(), size, 0, size, result, width);
openGlBytesToRBG(rawFrame.getFront().getByteBuffer(), size, size, size, result, width);
openGlBytesToRBG(rawFrame.getRight().getByteBuffer(), size, size * 2, size, result, width);
openGlBytesToRBG(rawFrame.getBack().getByteBuffer(), size, size * 3, size, result, width);
openGlBytesToRBG(rawFrame.getTop().getByteBuffer(), size, size, 0, result, width);
openGlBytesToRBG(rawFrame.getBottom().getByteBuffer(), size, size, size * 2, result, width);
ByteBufferPool.release(rawFrame.getLeft().getByteBuffer());
ByteBufferPool.release(rawFrame.getRight().getByteBuffer());
ByteBufferPool.release(rawFrame.getFront().getByteBuffer());
ByteBufferPool.release(rawFrame.getBack().getByteBuffer());
ByteBufferPool.release(rawFrame.getTop().getByteBuffer());
ByteBufferPool.release(rawFrame.getBottom().getByteBuffer());
return new RGBFrame(rawFrame.getFrameId(), new Dimension(width, height), result);
}
}

View File

@@ -1,7 +1,7 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.CubicOpenGlFrame;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.utils.ByteBufferPool;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import org.apache.commons.lang3.Validate;
@@ -10,7 +10,7 @@ import java.nio.ByteBuffer;
import static java.lang.Math.PI;
public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicOpenGlFrame, RGBFrame> {
public class EquirectangularToBitmapProcessor extends AbstractFrameProcessor<CubicOpenGlFrame, BitmapFrame> {
private static final byte IMAGE_BACK = 0;
private static final byte IMAGE_FRONT = 1;
private static final byte IMAGE_LEFT = 2;
@@ -26,7 +26,7 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
private final int[][] imageX;
private final int[][] imageY;
public EquirectangularToRGBProcessor(int outputWidth, int outputHeight, int sphericalFovX) {
public EquirectangularToBitmapProcessor(int outputWidth, int outputHeight, int sphericalFovX) {
// calculate the dimensions of the original equirectangular projection
// (before cropping according to FOV)
width = outputWidth;
@@ -103,16 +103,17 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
}
@Override
public RGBFrame process(CubicOpenGlFrame rawFrame) {
public BitmapFrame process(CubicOpenGlFrame rawFrame) {
Validate.isTrue(rawFrame.getLeft().getSize().getWidth() == frameSize, "Frame size must be %d but was %d",
frameSize, rawFrame.getLeft().getSize().getWidth());
ByteBuffer result = ByteBufferPool.allocate(width * height * 4);
int bpp = rawFrame.getLeft().getBytesPerPixel();
ByteBuffer result = ByteBufferPool.allocate(width * height * bpp);
ByteBuffer[] images = {
rawFrame.getBack().getByteBuffer(), rawFrame.getFront().getByteBuffer(),
rawFrame.getLeft().getByteBuffer(), rawFrame.getRight().getByteBuffer(),
rawFrame.getTop().getByteBuffer(), rawFrame.getBottom().getByteBuffer()
};
byte[] pixel = new byte[4];
byte[] pixel = new byte[bpp];
byte[] image;
int[] imageX, imageY;
for (int y = 0; y < height; y++) {
@@ -121,7 +122,7 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
imageY = this.imageY[y];
for (int x = 0; x < width; x++) {
ByteBuffer source = images[image[x]];
source.position((imageX[x] + imageY[x] * frameSize) * 4);
source.position((imageX[x] + imageY[x] * frameSize) * bpp);
source.get(pixel);
result.put(pixel);
}
@@ -134,7 +135,7 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
ByteBufferPool.release(rawFrame.getBack().getByteBuffer());
ByteBufferPool.release(rawFrame.getTop().getByteBuffer());
ByteBufferPool.release(rawFrame.getBottom().getByteBuffer());
return new RGBFrame(rawFrame.getFrameId(), new Dimension(width, height), result);
return new BitmapFrame(rawFrame.getFrameId(), new Dimension(width, height), bpp, result);
}
public int getFrameSize() {

View File

@@ -1,7 +1,7 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.ODSOpenGlFrame;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.utils.ByteBufferPool;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
@@ -9,25 +9,26 @@ import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import java.io.IOException;
import java.nio.ByteBuffer;
public class ODSToRGBProcessor extends AbstractFrameProcessor<ODSOpenGlFrame, RGBFrame> {
private final EquirectangularToRGBProcessor processor;
public class ODSToBitmapProcessor extends AbstractFrameProcessor<ODSOpenGlFrame, BitmapFrame> {
private final EquirectangularToBitmapProcessor processor;
public ODSToRGBProcessor(int outputWidth, int outputHeight, int sphericalFovX) {
processor = new EquirectangularToRGBProcessor(outputWidth, outputHeight / 2, sphericalFovX);
public ODSToBitmapProcessor(int outputWidth, int outputHeight, int sphericalFovX) {
processor = new EquirectangularToBitmapProcessor(outputWidth, outputHeight / 2, sphericalFovX);
}
@Override
public RGBFrame process(ODSOpenGlFrame rawFrame) {
RGBFrame leftFrame = processor.process(rawFrame.getLeft());
RGBFrame rightFrame = processor.process(rawFrame.getRight());
public BitmapFrame process(ODSOpenGlFrame rawFrame) {
BitmapFrame leftFrame = processor.process(rawFrame.getLeft());
BitmapFrame rightFrame = processor.process(rawFrame.getRight());
ReadableDimension size = new Dimension(leftFrame.getSize().getWidth(), leftFrame.getSize().getHeight() * 2);
ByteBuffer result = ByteBufferPool.allocate(size.getWidth() * size.getHeight() * 4);
int bpp = rawFrame.getLeft().getLeft().getBytesPerPixel();
ByteBuffer result = ByteBufferPool.allocate(size.getWidth() * size.getHeight() * bpp);
result.put(leftFrame.getByteBuffer());
result.put(rightFrame.getByteBuffer());
result.rewind();
ByteBufferPool.release(leftFrame.getByteBuffer());
ByteBufferPool.release(rightFrame.getByteBuffer());
return new RGBFrame(rawFrame.getFrameId(), size, result);
return new BitmapFrame(rawFrame.getFrameId(), size, bpp, result);
}
@Override

View File

@@ -1,21 +1,22 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import java.nio.ByteBuffer;
public class OpenGlToRGBProcessor extends AbstractFrameProcessor<OpenGlFrame, RGBFrame> {
public class OpenGlToBitmapProcessor extends AbstractFrameProcessor<OpenGlFrame, BitmapFrame> {
private byte[] row, rowSwap;
@Override
public RGBFrame process(OpenGlFrame rawFrame) {
public BitmapFrame process(OpenGlFrame rawFrame) {
// Flip whole image in place
ReadableDimension size = rawFrame.getSize();
int rowSize = size.getWidth() * 4;
int bpp = rawFrame.getBytesPerPixel();
int rowSize = size.getWidth() * bpp;
if (row == null || row.length < rowSize) {
row = new byte[rowSize];
rowSwap = new byte[rowSize];
@@ -37,6 +38,6 @@ public class OpenGlToRGBProcessor extends AbstractFrameProcessor<OpenGlFrame, RG
buffer.put(rowSwap);
}
buffer.rewind();
return new RGBFrame(rawFrame.getFrameId(), size, buffer);
return new BitmapFrame(rawFrame.getFrameId(), size, bpp, buffer);
}
}

View File

@@ -0,0 +1,26 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.frame.StereoscopicOpenGlFrame;
import com.replaymod.render.utils.ByteBufferPool;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import java.nio.ByteBuffer;
import static com.replaymod.render.utils.Utils.openGlBytesToBitmap;
public class StereoscopicToBitmapProcessor extends AbstractFrameProcessor<StereoscopicOpenGlFrame, BitmapFrame> {
@Override
public BitmapFrame process(StereoscopicOpenGlFrame rawFrame) {
ReadableDimension size = rawFrame.getLeft().getSize();
int width = size.getWidth();
int bpp = rawFrame.getLeft().getBytesPerPixel();
ByteBuffer result = ByteBufferPool.allocate(width * 2 * size.getHeight() * bpp);
openGlBytesToBitmap(rawFrame.getLeft(), 0, 0, result, width * 2);
openGlBytesToBitmap(rawFrame.getRight(), size.getWidth(), 0, result, width * 2);
ByteBufferPool.release(rawFrame.getLeft().getByteBuffer());
ByteBufferPool.release(rawFrame.getRight().getByteBuffer());
return new BitmapFrame(rawFrame.getFrameId(), new Dimension(width * 2, size.getHeight()), bpp, result);
}
}

View File

@@ -1,27 +0,0 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.StereoscopicOpenGlFrame;
import com.replaymod.render.utils.ByteBufferPool;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import java.nio.ByteBuffer;
import static com.replaymod.render.utils.Utils.openGlBytesToRBG;
public class StereoscopicToRGBProcessor extends AbstractFrameProcessor<StereoscopicOpenGlFrame, RGBFrame> {
@Override
public RGBFrame process(StereoscopicOpenGlFrame rawFrame) {
ReadableDimension size = rawFrame.getLeft().getSize();
int width = size.getWidth();
ByteBuffer leftBuffer = rawFrame.getLeft().getByteBuffer();
ByteBuffer rightBuffer = rawFrame.getRight().getByteBuffer();
ByteBuffer result = ByteBufferPool.allocate(width * 2 * size.getHeight() * 4);
openGlBytesToRBG(leftBuffer, width, 0, 0, result, width * 2);
openGlBytesToRBG(rightBuffer, width, size.getWidth(), 0, result, width * 2);
ByteBufferPool.release(leftBuffer);
ByteBufferPool.release(rightBuffer);
return new RGBFrame(rawFrame.getFrameId(), new Dimension(width * 2, size.getHeight()), result);
}
}

View File

@@ -14,19 +14,19 @@ import com.replaymod.render.capturer.WorldRenderer;
import com.replaymod.render.frame.CubicOpenGlFrame;
import com.replaymod.render.frame.ODSOpenGlFrame;
import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.frame.StereoscopicOpenGlFrame;
import com.replaymod.render.hooks.EntityRendererHandler;
import com.replaymod.render.processor.CubicToRGBProcessor;
import com.replaymod.render.processor.CubicToBitmapProcessor;
import com.replaymod.render.processor.DummyProcessor;
import com.replaymod.render.processor.EquirectangularToRGBProcessor;
import com.replaymod.render.processor.ODSToRGBProcessor;
import com.replaymod.render.processor.OpenGlToRGBProcessor;
import com.replaymod.render.processor.StereoscopicToRGBProcessor;
import com.replaymod.render.processor.EquirectangularToBitmapProcessor;
import com.replaymod.render.processor.ODSToBitmapProcessor;
import com.replaymod.render.processor.OpenGlToBitmapProcessor;
import com.replaymod.render.processor.StereoscopicToBitmapProcessor;
import com.replaymod.render.utils.PixelBufferObject;
public class Pipelines {
public static Pipeline newPipeline(RenderSettings.RenderMethod method, RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
public static Pipeline newPipeline(RenderSettings.RenderMethod method, RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
switch (method) {
case DEFAULT:
return newDefaultPipeline(renderInfo, consumer);
@@ -44,7 +44,7 @@ public class Pipelines {
throw new UnsupportedOperationException("Unknown method: " + method);
}
public static Pipeline<OpenGlFrame, RGBFrame> newDefaultPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
public static Pipeline<OpenGlFrame, BitmapFrame> newDefaultPipeline(RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);
FrameCapturer<OpenGlFrame> capturer;
@@ -53,10 +53,10 @@ public class Pipelines {
} else {
capturer = new SimpleOpenGlFrameCapturer(worldRenderer, renderInfo);
}
return new Pipeline<>(worldRenderer, capturer, new OpenGlToRGBProcessor(), consumer);
return new Pipeline<>(worldRenderer, capturer, new OpenGlToBitmapProcessor(), consumer);
}
public static Pipeline<StereoscopicOpenGlFrame, RGBFrame> newStereoscopicPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
public static Pipeline<StereoscopicOpenGlFrame, BitmapFrame> newStereoscopicPipeline(RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);
FrameCapturer<StereoscopicOpenGlFrame> capturer;
@@ -65,10 +65,10 @@ public class Pipelines {
} else {
capturer = new StereoscopicOpenGlFrameCapturer(worldRenderer, renderInfo);
}
return new Pipeline<>(worldRenderer, capturer, new StereoscopicToRGBProcessor(), consumer);
return new Pipeline<>(worldRenderer, capturer, new StereoscopicToBitmapProcessor(), consumer);
}
public static Pipeline<CubicOpenGlFrame, RGBFrame> newCubicPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
public static Pipeline<CubicOpenGlFrame, BitmapFrame> newCubicPipeline(RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);
FrameCapturer<CubicOpenGlFrame> capturer;
@@ -77,14 +77,14 @@ public class Pipelines {
} else {
capturer = new CubicOpenGlFrameCapturer(worldRenderer, renderInfo, settings.getVideoWidth() / 4);
}
return new Pipeline<>(worldRenderer, capturer, new CubicToRGBProcessor(), consumer);
return new Pipeline<>(worldRenderer, capturer, new CubicToBitmapProcessor(), consumer);
}
public static Pipeline<CubicOpenGlFrame, RGBFrame> newEquirectangularPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
public static Pipeline<CubicOpenGlFrame, BitmapFrame> newEquirectangularPipeline(RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);
EquirectangularToRGBProcessor processor = new EquirectangularToRGBProcessor(settings.getVideoWidth(),
EquirectangularToBitmapProcessor processor = new EquirectangularToBitmapProcessor(settings.getVideoWidth(),
settings.getVideoHeight(), settings.getSphericalFovX());
FrameCapturer<CubicOpenGlFrame> capturer;
@@ -96,11 +96,11 @@ public class Pipelines {
return new Pipeline<>(worldRenderer, capturer, processor, consumer);
}
public static Pipeline<ODSOpenGlFrame, RGBFrame> newODSPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
public static Pipeline<ODSOpenGlFrame, BitmapFrame> newODSPipeline(RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);
ODSToRGBProcessor processor = new ODSToRGBProcessor(settings.getVideoWidth(),
ODSToBitmapProcessor processor = new ODSToBitmapProcessor(settings.getVideoWidth(),
settings.getVideoHeight(), settings.getSphericalFovX());
FrameCapturer<ODSOpenGlFrame> capturer =
@@ -108,13 +108,13 @@ public class Pipelines {
return new Pipeline<>(worldRenderer, capturer, processor, consumer);
}
public static Pipeline<RGBFrame, RGBFrame> newBlendPipeline(RenderInfo renderInfo) {
public static Pipeline<BitmapFrame, BitmapFrame> newBlendPipeline(RenderInfo renderInfo) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);
FrameCapturer<RGBFrame> capturer = new BlendFrameCapturer(worldRenderer, renderInfo);
FrameConsumer<RGBFrame> consumer = new FrameConsumer<RGBFrame>() {
FrameCapturer<BitmapFrame> capturer = new BlendFrameCapturer(worldRenderer, renderInfo);
FrameConsumer<BitmapFrame> consumer = new FrameConsumer<BitmapFrame>() {
@Override
public void consume(RGBFrame frame) {
public void consume(BitmapFrame frame) {
}
@Override

View File

@@ -13,7 +13,7 @@ import com.replaymod.render.VideoWriter;
import com.replaymod.render.blend.BlendState;
import com.replaymod.render.capturer.RenderInfo;
import com.replaymod.render.events.ReplayRenderCallback;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.gui.GuiRenderingDone;
import com.replaymod.render.gui.GuiVideoRenderer;
import com.replaymod.render.metadata.MetadataInjector;
@@ -124,7 +124,7 @@ public class VideoRenderer implements RenderInfo {
this.renderingPipeline = Pipelines.newPipeline(settings.getRenderMethod(), this,
videoWriter = new VideoWriter(this) {
@Override
public void consume(RGBFrame frame) {
public void consume(BitmapFrame frame) {
gui.updatePreview(frame);
super.consume(frame);
}

View File

@@ -1,24 +1,41 @@
package com.replaymod.render.utils;
import com.replaymod.render.frame.OpenGlFrame;
import java.nio.ByteBuffer;
public class Utils {
/**
* Copies the rgb image (flipped vertically) to the specified position in the target buffer
* @param buffer Source image
* @param bufferWidth Source image width
* @param source Source image
* @param xOffset X offset in target image
* @param yOffset Y offset in target image
* @param to Target image
* @param width Target image width
*/
public static void openGlBytesToRBG(ByteBuffer buffer, int bufferWidth, int xOffset, int yOffset, ByteBuffer to, int width) {
byte[] rowBuf = new byte[bufferWidth * 4];
public static void openGlBytesToBitmap(OpenGlFrame source, int xOffset, int yOffset, ByteBuffer to, int width) {
openGlBytesToBitmap(
source.getByteBuffer(), source.getSize().getWidth(), source.getBytesPerPixel(),
xOffset, yOffset, to, width);
}
/**
* Copies the rgb image (flipped vertically) to the specified position in the target buffer
* @param buffer Source image
* @param bufferWidth Source image width
* @param bbp Bytes per pixel
* @param xOffset X offset in target image
* @param yOffset Y offset in target image
* @param to Target image
* @param width Target image width
*/
public static void openGlBytesToBitmap(ByteBuffer buffer, int bufferWidth, int bbp, int xOffset, int yOffset, ByteBuffer to, int width) {
byte[] rowBuf = new byte[bufferWidth * bbp];
// Copy image flipped vertically to target buffer
int rows = buffer.remaining() / 4 / bufferWidth;
int rows = buffer.remaining() / bbp / bufferWidth;
for (int i = 0; i < rows; i++) {
buffer.get(rowBuf);
to.position(((yOffset + rows - i - 1) * width + xOffset) * 4);
to.position(((yOffset + rows - i - 1) * width + xOffset) * bbp);
to.put(rowBuf);
}
to.rewind();