thin lens aproximation mode MVP

This commit is contained in:
2026-06-30 22:14:05 +04:00
parent 646577e97f
commit 3b070a7efc
7 changed files with 65 additions and 56 deletions

View File

@@ -1,21 +0,0 @@
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

@@ -12,8 +12,8 @@ public class RealLensOpenGlFrameCapturer
public static class Data implements CaptureData { public static class Data implements CaptureData {
public final float dx, dy, dz; public float dx, dy, dz;
public final float yaw, pitch; public float yaw, pitch;
public Data(float dx, float dy, float dz, public Data(float dx, float dy, float dz,
float yaw, float pitch) { float yaw, float pitch) {
@@ -25,12 +25,47 @@ public class RealLensOpenGlFrameCapturer
} }
} }
private static final Data[] CAMERAS = { private static Data[] golden_disk(int n, float r) {
new Data( 0.25f, 0.00f, 0f, 0f, 0f),
new Data( 0.00f, 0.25f, 0f, 0f, 0f), Data[] points = new Data[n];
new Data(-0.25f, 0.00f, 0f, 0f, 0f),
new Data( 0.00f, -0.25f, 0f, 0f, 0f) final float GOLDEN_ANGLE = (float) (Math.PI * (3.0 - Math.sqrt(5.0)));
};
for (int i = 0; i < n; i++) {
float rr = r * (float) Math.sqrt((float) i / n);
float t = i * GOLDEN_ANGLE;
points[i] = new Data(
rr * (float) Math.cos(t),
rr * (float) Math.sin(t),
0f, 0f, 0f
);
}
return points;
}
private static final float FOCAL_DISTANCE = 5.0f;
private static final float APERTURE_RADIUS = 0.05f;
private static final int SAMPLES = 64;
private static Data[] calculateCameras() {
Data[] cameras = golden_disk(SAMPLES, APERTURE_RADIUS);
for (Data cam : cameras) {
// Направление от смещённой камеры к фокальной точке (0, 0, FOCAL_DISTANCE)
float dirX = 0 - cam.dx;
float dirY = 0 - cam.dy;
float dirZ = FOCAL_DISTANCE - cam.dz;
// Вычисляем yaw и pitch из направления
cam.yaw = (float) -Math.toDegrees(Math.atan2(dirX, dirZ));
cam.pitch = (float) Math.toDegrees(Math.atan2(dirY, Math.sqrt(dirX*dirX + dirZ*dirZ)));
}
return cameras;
}
public RealLensOpenGlFrameCapturer( public RealLensOpenGlFrameCapturer(
WorldRenderer worldRenderer, WorldRenderer worldRenderer,
@@ -41,30 +76,19 @@ public class RealLensOpenGlFrameCapturer
@Override @Override
public Map<Channel, RealLensOpenGlFrame> process() { public Map<Channel, RealLensOpenGlFrame> process() {
float partialTicks = renderInfo.updateForNextFrame(); float partialTicks = renderInfo.updateForNextFrame();
int frameId = framesDone++; int frameId = framesDone++;
OpenGlFrame[] frames = new OpenGlFrame[CAMERAS.length]; Data[] cameras = calculateCameras();
try { OpenGlFrame[] frames = new OpenGlFrame[cameras.length];
for (int i = 0; i < CAMERAS.length; i++) {
RealLensCameraContext.set(CAMERAS[i]); for (int i = 0; i < cameras.length; i++) {
// CAMERAS[i] передаётся в renderFrame → worldRenderer.renderWorld(partialTicks, CAMERAS[i])
frames[i] = renderFrame( // → EntityRendererHandler.data = CAMERAS[i] (автоматически)
frameId, frames[i] = renderFrame(frameId, partialTicks, cameras[i]);
partialTicks,
CAMERAS[i]
);
}
} finally {
RealLensCameraContext.clear();
} }
return Collections.singletonMap( return Collections.singletonMap(Channel.BRGA, new RealLensOpenGlFrame(frames));
Channel.BRGA,
new RealLensOpenGlFrame(frames)
);
} }
} }

View File

@@ -1,10 +1,10 @@
package com.replaymod.render.mixin; package com.replaymod.render.mixin;
import com.replaymod.render.capturer.RealLensOpenGlFrameCapturer; import com.replaymod.render.capturer.RealLensOpenGlFrameCapturer;
import com.replaymod.render.capturer.RealLensCameraContext;
import com.replaymod.render.hooks.EntityRendererHandler; import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Matrix4f;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -18,7 +18,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//#endif //#endif
@Mixin(GameRenderer.class) @Mixin(GameRenderer.class)
public abstract class Mixin_RealLens_Camera { public abstract class Mixin_RealLens_Camera implements EntityRendererHandler.IEntityRenderer {
//#if MC>=12005 //#if MC>=12005
//#if MC>=12100 //#if MC>=12100
@@ -31,10 +31,8 @@ public abstract class Mixin_RealLens_Camera {
@Inject(method = "renderWorld", at = @At("HEAD")) @Inject(method = "renderWorld", at = @At("HEAD"))
private void realLens_applyCameraTransform(float partialTicks, long frameStartNano, MatrixStack matrixStack, CallbackInfo ci) { private void realLens_applyCameraTransform(float partialTicks, long frameStartNano, MatrixStack matrixStack, CallbackInfo ci) {
//#endif //#endif
EntityRendererHandler handler = replayModRender_getHandler();
RealLensOpenGlFrameCapturer.Data cam = RealLensCameraContext.get(); if (!(handler != null && handler.data instanceof RealLensOpenGlFrameCapturer.Data)) {
if (cam == null) {
System.out.println("renderWorld WITHOUT camera context!");
//#if MC>=12005 //#if MC>=12005
//$$ return matrix; //$$ return matrix;
//#else //#else
@@ -42,14 +40,22 @@ public abstract class Mixin_RealLens_Camera {
//#endif //#endif
} }
RealLensOpenGlFrameCapturer.Data cam = (RealLensOpenGlFrameCapturer.Data) handler.data;
//#if MC>=12005 //#if MC>=12005
//$$ matrix.translateLocal(cam.dx, cam.dy, cam.dz); //$$ matrix.translateLocal(cam.dx, cam.dy, cam.dz);
//$$ return matrix;
//#else //#else
matrixStack.translate(cam.dx, cam.dy, cam.dz); matrixStack.translate(cam.dx, cam.dy, cam.dz);
//#endif //#endif
// In Mixin_RealLens_Camera, add rotation after translation
//#if MC>=12005 //#if MC>=12005
//$$ return matrix; //$$ matrix.rotateLocal((float) Math.toRadians(cam.pitch), 1, 0, 0);
//$$ matrix.rotateLocal((float) Math.toRadians(cam.yaw), 0, 1, 0);
//#else
matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(cam.pitch));
matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(cam.yaw));
//#endif //#endif
} }
} }

View File

@@ -55,9 +55,9 @@ public class RealLensToBitmapProcessor
int a = (bpp == 4) ? (converted.get(i + 3) & 0xFF) : 255; int a = (bpp == 4) ? (converted.get(i + 3) & 0xFF) : 255;
// swap R and B here // swap R and B here
accumulator[i] += r; accumulator[i] += b;
accumulator[i + 1] += g; accumulator[i + 1] += g;
accumulator[i + 2] += b; accumulator[i + 2] += r;
if (bpp == 4) { if (bpp == 4) {
accumulator[i + 3] += a; accumulator[i + 3] += a;

View File

View File

View File