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() {
|
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() {
|
public String getFileExtension() {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import com.replaymod.render.frame.OpenGlFrame;
|
|||||||
import com.replaymod.render.rendering.Frame;
|
import com.replaymod.render.rendering.Frame;
|
||||||
import com.replaymod.render.utils.ByteBufferPool;
|
import com.replaymod.render.utils.ByteBufferPool;
|
||||||
import com.replaymod.render.utils.PixelBufferObject;
|
import com.replaymod.render.utils.PixelBufferObject;
|
||||||
import net.minecraft.client.renderer.OpenGlHelper;
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL12;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -19,7 +19,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
|
|||||||
super(worldRenderer, renderInfo);
|
super(worldRenderer, renderInfo);
|
||||||
|
|
||||||
data = type.getEnumConstants();
|
data = type.getEnumConstants();
|
||||||
int bufferSize = framePixels * 3 * data.length;
|
int bufferSize = framePixels * 4 * data.length;
|
||||||
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
||||||
otherPBO = 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();
|
ByteBuffer pboBuffer = pbo.mapReadOnly();
|
||||||
|
|
||||||
OpenGlFrame[] frames = new OpenGlFrame[data.length];
|
OpenGlFrame[] frames = new OpenGlFrame[data.length];
|
||||||
int frameBufferSize = getFrameWidth() * getFrameHeight() * 3;
|
int frameBufferSize = getFrameWidth() * getFrameHeight() * 4;
|
||||||
for (int i = 0; i < frames.length; i++) {
|
for (int i = 0; i < frames.length; i++) {
|
||||||
ByteBuffer frameBuffer = ByteBufferPool.allocate(frameBufferSize);
|
ByteBuffer frameBuffer = ByteBufferPool.allocate(frameBufferSize);
|
||||||
pboBuffer.limit(pboBuffer.position() + 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) {
|
protected OpenGlFrame captureFrame(int frameId, D captureData) {
|
||||||
pbo.bind();
|
pbo.bind();
|
||||||
|
|
||||||
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
|
int offset = captureData.ordinal() * getFrameWidth() * getFrameHeight() * 4;
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
frameBuffer().bindFramebuffer(true);
|
||||||
|
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, offset);
|
||||||
int offset = captureData.ordinal() * getFrameWidth() * getFrameHeight() * 3;
|
frameBuffer().unbindFramebuffer();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
pbo.unbind();
|
pbo.unbind();
|
||||||
return null;
|
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.ReadableDimension;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.WritableDimension;
|
import de.johni0702.minecraft.gui.utils.lwjgl.WritableDimension;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.OpenGlHelper;
|
|
||||||
import net.minecraft.client.shader.Framebuffer;
|
import net.minecraft.client.shader.Framebuffer;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL12;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
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) {
|
protected OpenGlFrame captureFrame(int frameId, D captureData) {
|
||||||
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
|
ByteBuffer buffer = ByteBufferPool.allocate(getFrameWidth() * getFrameHeight() * 4);
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
frameBuffer().bindFramebuffer(true);
|
||||||
|
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer);
|
||||||
ByteBuffer buffer = ByteBufferPool.allocate(getFrameWidth() * getFrameHeight() * 3);
|
frameBuffer().unbindFramebuffer();
|
||||||
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);
|
|
||||||
}
|
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
|
|
||||||
return new OpenGlFrame(frameId, new Dimension(getFrameWidth(), getFrameHeight()), buffer);
|
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.ByteBufferPool;
|
||||||
import com.replaymod.render.utils.PixelBufferObject;
|
import com.replaymod.render.utils.PixelBufferObject;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||||
import net.minecraft.client.renderer.OpenGlHelper;
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL12;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -18,7 +18,7 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer<OpenGlFram
|
|||||||
super(worldRenderer, renderInfo);
|
super(worldRenderer, renderInfo);
|
||||||
|
|
||||||
ReadableDimension size = renderInfo.getFrameSize();
|
ReadableDimension size = renderInfo.getFrameSize();
|
||||||
bufferSize = size.getHeight() * size.getWidth() * 3;
|
bufferSize = size.getHeight() * size.getWidth() * 4;
|
||||||
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
||||||
otherPBO = 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) {
|
protected OpenGlFrame captureFrame(int frameId, CaptureData data) {
|
||||||
pbo.bind();
|
pbo.bind();
|
||||||
|
|
||||||
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
|
frameBuffer().bindFramebuffer(true);
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, 0);
|
||||||
|
frameBuffer().unbindFramebuffer();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
pbo.unbind();
|
pbo.unbind();
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ public class RGBFrame implements Frame {
|
|||||||
private final ByteBuffer byteBuffer;
|
private final ByteBuffer byteBuffer;
|
||||||
|
|
||||||
public RGBFrame(int frameId, ReadableDimension size, 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",
|
"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.frameId = frameId;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.byteBuffer = byteBuffer;
|
this.byteBuffer = byteBuffer;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class CubicToRGBProcessor extends AbstractFrameProcessor<CubicOpenGlFrame
|
|||||||
int size = rawFrame.getLeft().getSize().getWidth();
|
int size = rawFrame.getLeft().getSize().getWidth();
|
||||||
int width = size * 4;
|
int width = size * 4;
|
||||||
int height = size * 3;
|
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.getLeft().getByteBuffer(), size, 0, size, result, width);
|
||||||
openGlBytesToRBG(rawFrame.getFront().getByteBuffer(), size, size, size, result, width);
|
openGlBytesToRBG(rawFrame.getFront().getByteBuffer(), size, size, size, result, width);
|
||||||
openGlBytesToRBG(rawFrame.getRight().getByteBuffer(), size, size * 2, 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) {
|
public RGBFrame process(CubicOpenGlFrame rawFrame) {
|
||||||
Validate.isTrue(rawFrame.getLeft().getSize().getWidth() == frameSize, "Frame size must be %d but was %d",
|
Validate.isTrue(rawFrame.getLeft().getSize().getWidth() == frameSize, "Frame size must be %d but was %d",
|
||||||
frameSize, rawFrame.getLeft().getSize().getWidth());
|
frameSize, rawFrame.getLeft().getSize().getWidth());
|
||||||
ByteBuffer result = ByteBufferPool.allocate(width * height * 3);
|
ByteBuffer result = ByteBufferPool.allocate(width * height * 4);
|
||||||
ByteBuffer[] images = {
|
ByteBuffer[] images = {
|
||||||
rawFrame.getBack().getByteBuffer(), rawFrame.getFront().getByteBuffer(),
|
rawFrame.getBack().getByteBuffer(), rawFrame.getFront().getByteBuffer(),
|
||||||
rawFrame.getLeft().getByteBuffer(), rawFrame.getRight().getByteBuffer(),
|
rawFrame.getLeft().getByteBuffer(), rawFrame.getRight().getByteBuffer(),
|
||||||
rawFrame.getTop().getByteBuffer(), rawFrame.getBottom().getByteBuffer()
|
rawFrame.getTop().getByteBuffer(), rawFrame.getBottom().getByteBuffer()
|
||||||
};
|
};
|
||||||
byte[] pixel = new byte[3];
|
byte[] pixel = new byte[4];
|
||||||
byte[] image;
|
byte[] image;
|
||||||
int[] imageX, imageY;
|
int[] imageX, imageY;
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
@@ -123,7 +123,7 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
|
|||||||
imageY = this.imageY[y];
|
imageY = this.imageY[y];
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
ByteBuffer source = images[image[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);
|
source.get(pixel);
|
||||||
result.put(pixel);
|
result.put(pixel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class ODSToRGBProcessor extends AbstractFrameProcessor<ODSOpenGlFrame, RG
|
|||||||
RGBFrame leftFrame = processor.process(rawFrame.getLeft());
|
RGBFrame leftFrame = processor.process(rawFrame.getLeft());
|
||||||
RGBFrame rightFrame = processor.process(rawFrame.getRight());
|
RGBFrame rightFrame = processor.process(rawFrame.getRight());
|
||||||
ReadableDimension size = new Dimension(leftFrame.getSize().getWidth(), leftFrame.getSize().getHeight() * 2);
|
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(leftFrame.getByteBuffer());
|
||||||
result.put(rightFrame.getByteBuffer());
|
result.put(rightFrame.getByteBuffer());
|
||||||
result.rewind();
|
result.rewind();
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class OpenGlToRGBProcessor extends AbstractFrameProcessor<OpenGlFrame, RG
|
|||||||
// Flip whole image in place
|
// Flip whole image in place
|
||||||
|
|
||||||
ReadableDimension size = rawFrame.getSize();
|
ReadableDimension size = rawFrame.getSize();
|
||||||
int rowSize = size.getWidth() * 3;
|
int rowSize = size.getWidth() * 4;
|
||||||
if (row == null || row.length < rowSize) {
|
if (row == null || row.length < rowSize) {
|
||||||
row = new byte[rowSize];
|
row = new byte[rowSize];
|
||||||
rowSwap = new byte[rowSize];
|
rowSwap = new byte[rowSize];
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class StereoscopicToRGBProcessor extends AbstractFrameProcessor<Stereosco
|
|||||||
int width = size.getWidth();
|
int width = size.getWidth();
|
||||||
ByteBuffer leftBuffer = rawFrame.getLeft().getByteBuffer();
|
ByteBuffer leftBuffer = rawFrame.getLeft().getByteBuffer();
|
||||||
ByteBuffer rightBuffer = rawFrame.getRight().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(leftBuffer, width, 0, 0, result, width * 2);
|
||||||
openGlBytesToRBG(rightBuffer, width, size.getWidth(), 0, result, width * 2);
|
openGlBytesToRBG(rightBuffer, width, size.getWidth(), 0, result, width * 2);
|
||||||
ByteBufferPool.release(leftBuffer);
|
ByteBufferPool.release(leftBuffer);
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ public class Utils {
|
|||||||
* @param width Target image width
|
* @param width Target image width
|
||||||
*/
|
*/
|
||||||
public static void openGlBytesToRBG(ByteBuffer buffer, int bufferWidth, int xOffset, int yOffset, ByteBuffer to, int 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
|
// 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++) {
|
for (int i = 0; i < rows; i++) {
|
||||||
buffer.get(rowBuf);
|
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.put(rowBuf);
|
||||||
}
|
}
|
||||||
to.rewind();
|
to.rewind();
|
||||||
|
|||||||
Reference in New Issue
Block a user