test worked

This commit is contained in:
2026-06-30 11:44:24 +04:00
parent a4c8dafa07
commit 646577e97f
9 changed files with 302 additions and 1 deletions

View File

@@ -25,7 +25,7 @@ import static com.replaymod.render.ReplayModRender.LOGGER;
public class RenderSettings {
public enum RenderMethod {
DEFAULT, STEREOSCOPIC, CUBIC, EQUIRECTANGULAR, ODS, BLEND;
DEFAULT, REALLENS, STEREOSCOPIC, CUBIC, EQUIRECTANGULAR, ODS, BLEND;
@Override
public String toString() {

View File

@@ -0,0 +1,21 @@
package com.replaymod.render.capturer;
public final class RealLensCameraContext {
private static final ThreadLocal<RealLensOpenGlFrameCapturer.Data> CURRENT =
new ThreadLocal<>();
private RealLensCameraContext() {}
public static void set(RealLensOpenGlFrameCapturer.Data data) {
CURRENT.set(data);
}
public static RealLensOpenGlFrameCapturer.Data get() {
return CURRENT.get();
}
public static void clear() {
CURRENT.remove();
}
}

View File

@@ -0,0 +1,70 @@
package com.replaymod.render.capturer;
import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.frame.RealLensOpenGlFrame;
import com.replaymod.render.rendering.Channel;
import java.util.Collections;
import java.util.Map;
public class RealLensOpenGlFrameCapturer
extends OpenGlFrameCapturer<RealLensOpenGlFrame, RealLensOpenGlFrameCapturer.Data> {
public static class Data implements CaptureData {
public final float dx, dy, dz;
public final float yaw, pitch;
public Data(float dx, float dy, float dz,
float yaw, float pitch) {
this.dx = dx;
this.dy = dy;
this.dz = dz;
this.yaw = yaw;
this.pitch = pitch;
}
}
private static final Data[] CAMERAS = {
new Data( 0.25f, 0.00f, 0f, 0f, 0f),
new Data( 0.00f, 0.25f, 0f, 0f, 0f),
new Data(-0.25f, 0.00f, 0f, 0f, 0f),
new Data( 0.00f, -0.25f, 0f, 0f, 0f)
};
public RealLensOpenGlFrameCapturer(
WorldRenderer worldRenderer,
RenderInfo renderInfo
) {
super(worldRenderer, renderInfo);
}
@Override
public Map<Channel, RealLensOpenGlFrame> process() {
float partialTicks = renderInfo.updateForNextFrame();
int frameId = framesDone++;
OpenGlFrame[] frames = new OpenGlFrame[CAMERAS.length];
try {
for (int i = 0; i < CAMERAS.length; i++) {
RealLensCameraContext.set(CAMERAS[i]);
frames[i] = renderFrame(
frameId,
partialTicks,
CAMERAS[i]
);
}
} finally {
RealLensCameraContext.clear();
}
return Collections.singletonMap(
Channel.BRGA,
new RealLensOpenGlFrame(frames)
);
}
}

View File

@@ -0,0 +1,39 @@
package com.replaymod.render.frame;
import com.replaymod.render.rendering.Frame;
import org.apache.commons.lang3.Validate;
public class RealLensOpenGlFrame implements Frame {
private final OpenGlFrame[] frames;
public RealLensOpenGlFrame(OpenGlFrame[] frames) {
Validate.notNull(frames, "frames");
Validate.isTrue(frames.length > 0, "frames must not be empty");
int frameId = frames[0].getFrameId();
int remaining = frames[0].getByteBuffer().remaining();
for (OpenGlFrame frame : frames) {
Validate.isTrue(
frame.getFrameId() == frameId,
"Frame ids do not match."
);
Validate.isTrue(
frame.getByteBuffer().remaining() == remaining,
"Buffer sizes do not match."
);
}
this.frames = frames;
}
@Override
public int getFrameId() {
return frames[0].getFrameId();
}
public OpenGlFrame[] getFrames() {
return frames;
}
}

View File

@@ -0,0 +1,55 @@
package com.replaymod.render.mixin;
import com.replaymod.render.capturer.RealLensOpenGlFrameCapturer;
import com.replaymod.render.capturer.RealLensCameraContext;
import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//#if MC>=12005
//$$ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
//$$ import org.joml.Matrix4f;
//#endif
@Mixin(GameRenderer.class)
public abstract class Mixin_RealLens_Camera {
//#if MC>=12005
//#if MC>=12100
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotation(Lorg/joml/Quaternionfc;)Lorg/joml/Matrix4f;"))
//#else
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotationXYZ(FFF)Lorg/joml/Matrix4f;"))
//#endif
//$$ private Matrix4f realLens_applyCameraTransform(Matrix4f matrix) {
//#else
@Inject(method = "renderWorld", at = @At("HEAD"))
private void realLens_applyCameraTransform(float partialTicks, long frameStartNano, MatrixStack matrixStack, CallbackInfo ci) {
//#endif
RealLensOpenGlFrameCapturer.Data cam = RealLensCameraContext.get();
if (cam == null) {
System.out.println("renderWorld WITHOUT camera context!");
//#if MC>=12005
//$$ return matrix;
//#else
return;
//#endif
}
//#if MC>=12005
//$$ matrix.translateLocal(cam.dx, cam.dy, cam.dz);
//#else
matrixStack.translate(cam.dx, cam.dy, cam.dz);
//#endif
//#if MC>=12005
//$$ return matrix;
//#endif
}
}

View File

@@ -0,0 +1,101 @@
package com.replaymod.render.processor;
import com.replaymod.render.frame.BitmapFrame;
import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.frame.RealLensOpenGlFrame;
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 RealLensToBitmapProcessor
extends AbstractFrameProcessor<RealLensOpenGlFrame, BitmapFrame> {
@Override
public BitmapFrame process(RealLensOpenGlFrame rawFrame) {
OpenGlFrame[] frames = rawFrame.getFrames();
OpenGlFrame first = frames[0];
int width = first.getSize().getWidth();
int height = first.getSize().getHeight();
int bpp = first.getBytesPerPixel();
int totalBytes = width * height * bpp;
int[] accumulator = new int[totalBytes];
ByteBuffer converted = ByteBufferPool.allocate(totalBytes);
try {
for (OpenGlFrame frame : frames) {
converted.clear();
// BGRA -> bitmap layout (still BGRA at this point)
openGlBytesToBitmap(
frame,
0,
0,
converted,
width
);
converted.rewind();
// accumulate per channel with B <-> R swap
for (int i = 0; i < totalBytes; i += bpp) {
int b = converted.get(i) & 0xFF;
int g = converted.get(i + 1) & 0xFF;
int r = converted.get(i + 2) & 0xFF;
int a = (bpp == 4) ? (converted.get(i + 3) & 0xFF) : 255;
// swap R and B here
accumulator[i] += r;
accumulator[i + 1] += g;
accumulator[i + 2] += b;
if (bpp == 4) {
accumulator[i + 3] += a;
}
}
}
ByteBuffer output = ByteBufferPool.allocate(totalBytes);
int samples = frames.length;
for (int i = 0; i < totalBytes; i += bpp) {
output.put((byte) (accumulator[i] / samples)); // R
output.put((byte) (accumulator[i + 1] / samples)); // G
output.put((byte) (accumulator[i + 2] / samples)); // B
if (bpp == 4) {
output.put((byte) (accumulator[i + 3] / samples)); // A
}
}
output.rewind();
return new BitmapFrame(
rawFrame.getFrameId(),
new Dimension(width, height),
bpp,
output
);
} finally {
ByteBufferPool.release(converted);
for (OpenGlFrame frame : frames) {
ByteBufferPool.release(frame.getByteBuffer());
}
}
}
}

View File

@@ -24,6 +24,9 @@ import com.replaymod.render.processor.ODSToBitmapProcessor;
import com.replaymod.render.processor.OpenGlToBitmapProcessor;
import com.replaymod.render.processor.StereoscopicToBitmapProcessor;
import com.replaymod.render.utils.PixelBufferObject;
import com.replaymod.render.capturer.RealLensOpenGlFrameCapturer;
import com.replaymod.render.frame.RealLensOpenGlFrame;
import com.replaymod.render.processor.RealLensToBitmapProcessor;
import java.util.Map;
@@ -32,6 +35,8 @@ public class Pipelines {
switch (method) {
case DEFAULT:
return newDefaultPipeline(renderInfo, consumer);
case REALLENS:
return newRealLensPipeline(renderInfo, consumer);
case STEREOSCOPIC:
return newStereoscopicPipeline(renderInfo, consumer);
case CUBIC:
@@ -58,6 +63,15 @@ public class Pipelines {
return new Pipeline<>(worldRenderer, capturer, new OpenGlToBitmapProcessor(), consumer);
}
public static Pipeline<RealLensOpenGlFrame, BitmapFrame> newRealLensPipeline(
RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);
FrameCapturer<RealLensOpenGlFrame> capturer =
new RealLensOpenGlFrameCapturer(worldRenderer, renderInfo);
return new Pipeline<>(worldRenderer, capturer, new RealLensToBitmapProcessor(), consumer);
}
public static Pipeline<StereoscopicOpenGlFrame, BitmapFrame> newStereoscopicPipeline(RenderInfo renderInfo, FrameConsumer<BitmapFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings();
WorldRenderer worldRenderer = new EntityRendererHandler(settings, renderInfo);