Render to BGRA instead of RGB format for better performance on most GPUs
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user