Render to BGRA instead of RGB format for better performance on most GPUs

This commit is contained in:
Jonas Herzig
2019-03-13 15:27:53 +01:00
parent 27efc3c717
commit 443c1ca2af
11 changed files with 30 additions and 51 deletions

View File

@@ -72,7 +72,7 @@ public class RenderSettings {
}
public String getValue() {
return "-y -f rawvideo -pix_fmt rgb24 -s %WIDTH%x%HEIGHT% -r %FPS% -i - %FILTERS%" + preset;
return "-y -f rawvideo -pix_fmt bgra -s %WIDTH%x%HEIGHT% -r %FPS% -i - %FILTERS%" + preset;
}
public String getFileExtension() {

View File

@@ -4,8 +4,8 @@ import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.rendering.Frame;
import com.replaymod.render.utils.ByteBufferPool;
import com.replaymod.render.utils.PixelBufferObject;
import net.minecraft.client.renderer.OpenGlHelper;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -19,7 +19,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
super(worldRenderer, renderInfo);
data = type.getEnumConstants();
int bufferSize = framePixels * 3 * data.length;
int bufferSize = framePixels * 4 * data.length;
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
otherPBO = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
}
@@ -47,7 +47,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
ByteBuffer pboBuffer = pbo.mapReadOnly();
OpenGlFrame[] frames = new OpenGlFrame[data.length];
int frameBufferSize = getFrameWidth() * getFrameHeight() * 3;
int frameBufferSize = getFrameWidth() * getFrameHeight() * 4;
for (int i = 0; i < frames.length; i++) {
ByteBuffer frameBuffer = ByteBufferPool.allocate(frameBufferSize);
pboBuffer.limit(pboBuffer.position() + frameBufferSize);
@@ -79,17 +79,10 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
protected OpenGlFrame captureFrame(int frameId, D captureData) {
pbo.bind();
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
int offset = captureData.ordinal() * getFrameWidth() * getFrameHeight() * 3;
if (OpenGlHelper.isFramebufferEnabled()) {
frameBuffer().bindFramebufferTexture();
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, offset);
frameBuffer().unbindFramebufferTexture();
} else {
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, offset);
}
int offset = captureData.ordinal() * getFrameWidth() * getFrameHeight() * 4;
frameBuffer().bindFramebuffer(true);
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, offset);
frameBuffer().unbindFramebuffer();
pbo.unbind();
return null;

View File

@@ -9,9 +9,9 @@ import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import de.johni0702.minecraft.gui.utils.lwjgl.WritableDimension;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.shader.Framebuffer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -97,17 +97,10 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
}
protected OpenGlFrame captureFrame(int frameId, D captureData) {
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
ByteBuffer buffer = ByteBufferPool.allocate(getFrameWidth() * getFrameHeight() * 3);
if (OpenGlHelper.isFramebufferEnabled()) {
frameBuffer().bindFramebufferTexture();
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, buffer);
frameBuffer().unbindFramebufferTexture();
} else {
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, buffer);
}
ByteBuffer buffer = ByteBufferPool.allocate(getFrameWidth() * getFrameHeight() * 4);
frameBuffer().bindFramebuffer(true);
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer);
frameBuffer().unbindFramebuffer();
buffer.rewind();
return new OpenGlFrame(frameId, new Dimension(getFrameWidth(), getFrameHeight()), buffer);

View File

@@ -4,8 +4,8 @@ import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.utils.ByteBufferPool;
import com.replaymod.render.utils.PixelBufferObject;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import net.minecraft.client.renderer.OpenGlHelper;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -18,7 +18,7 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer<OpenGlFram
super(worldRenderer, renderInfo);
ReadableDimension size = renderInfo.getFrameSize();
bufferSize = size.getHeight() * size.getWidth() * 3;
bufferSize = size.getHeight() * size.getWidth() * 4;
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
otherPBO = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
}
@@ -64,16 +64,9 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer<OpenGlFram
protected OpenGlFrame captureFrame(int frameId, CaptureData data) {
pbo.bind();
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
if (OpenGlHelper.isFramebufferEnabled()) {
frameBuffer().bindFramebufferTexture();
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, 0);
frameBuffer().unbindFramebufferTexture();
} else {
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, 0);
}
frameBuffer().bindFramebuffer(true);
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, 0);
frameBuffer().unbindFramebuffer();
pbo.unbind();
return null;

View File

@@ -18,9 +18,9 @@ public class RGBFrame implements Frame {
private final ByteBuffer byteBuffer;
public RGBFrame(int frameId, ReadableDimension size, ByteBuffer byteBuffer) {
Validate.isTrue(size.getWidth() * size.getHeight() * 3 == byteBuffer.remaining(),
Validate.isTrue(size.getWidth() * size.getHeight() * 4 == byteBuffer.remaining(),
"Buffer size is %d (cap: %d) but should be %d",
byteBuffer.remaining(), byteBuffer.capacity(), size.getWidth() * size.getHeight() * 3);
byteBuffer.remaining(), byteBuffer.capacity(), size.getWidth() * size.getHeight() * 4);
this.frameId = frameId;
this.size = size;
this.byteBuffer = byteBuffer;

View File

@@ -15,7 +15,7 @@ public class CubicToRGBProcessor extends AbstractFrameProcessor<CubicOpenGlFrame
int size = rawFrame.getLeft().getSize().getWidth();
int width = size * 4;
int height = size * 3;
ByteBuffer result = ByteBufferPool.allocate(width * height * 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);

View File

@@ -108,13 +108,13 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
public RGBFrame 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 * 3);
ByteBuffer result = ByteBufferPool.allocate(width * height * 4);
ByteBuffer[] images = {
rawFrame.getBack().getByteBuffer(), rawFrame.getFront().getByteBuffer(),
rawFrame.getLeft().getByteBuffer(), rawFrame.getRight().getByteBuffer(),
rawFrame.getTop().getByteBuffer(), rawFrame.getBottom().getByteBuffer()
};
byte[] pixel = new byte[3];
byte[] pixel = new byte[4];
byte[] image;
int[] imageX, imageY;
for (int y = 0; y < height; y++) {
@@ -123,7 +123,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) * 3);
source.position((imageX[x] + imageY[x] * frameSize) * 4);
source.get(pixel);
result.put(pixel);
}

View File

@@ -21,7 +21,7 @@ public class ODSToRGBProcessor extends AbstractFrameProcessor<ODSOpenGlFrame, RG
RGBFrame leftFrame = processor.process(rawFrame.getLeft());
RGBFrame rightFrame = processor.process(rawFrame.getRight());
ReadableDimension size = new Dimension(leftFrame.getSize().getWidth(), leftFrame.getSize().getHeight() * 2);
ByteBuffer result = ByteBufferPool.allocate(size.getWidth() * size.getHeight() * 3);
ByteBuffer result = ByteBufferPool.allocate(size.getWidth() * size.getHeight() * 4);
result.put(leftFrame.getByteBuffer());
result.put(rightFrame.getByteBuffer());
result.rewind();

View File

@@ -15,7 +15,7 @@ public class OpenGlToRGBProcessor extends AbstractFrameProcessor<OpenGlFrame, RG
// Flip whole image in place
ReadableDimension size = rawFrame.getSize();
int rowSize = size.getWidth() * 3;
int rowSize = size.getWidth() * 4;
if (row == null || row.length < rowSize) {
row = new byte[rowSize];
rowSwap = new byte[rowSize];

View File

@@ -17,7 +17,7 @@ public class StereoscopicToRGBProcessor extends AbstractFrameProcessor<Stereosco
int width = size.getWidth();
ByteBuffer leftBuffer = rawFrame.getLeft().getByteBuffer();
ByteBuffer rightBuffer = rawFrame.getRight().getByteBuffer();
ByteBuffer result = ByteBufferPool.allocate(width * 2 * size.getHeight() * 3);
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);

View File

@@ -13,12 +13,12 @@ public class Utils {
* @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 * 3];
byte[] rowBuf = new byte[bufferWidth * 4];
// Copy image flipped vertically to target buffer
int rows = buffer.remaining() / 3 / bufferWidth;
int rows = buffer.remaining() / 4 / bufferWidth;
for (int i = 0; i < rows; i++) {
buffer.get(rowBuf);
to.position(((yOffset + rows - i - 1) * width + xOffset) * 3);
to.position(((yOffset + rows - i - 1) * width + xOffset) * 4);
to.put(rowBuf);
}
to.rewind();