Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,4 @@ core.lib
libnvidia-ngx-dlss*
include/
shaders/
libxess*
libxess*.github/copilot-instructions.md
14 changes: 9 additions & 5 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@ Radiance是一个Minecraft Mod,旨在将原版的OpenGL渲染器完全替换

从[这个](https://github.com/NVIDIA/DLSS/tree/v310.5.3/lib/Windows_x86_64/rel)路径中下载如下列表中的文件到`.minecraft/radiance`文件夹(如果文件夹不存在,请创建一个)。

* `nvngx_dlss.dll`
* `nvngx_dlssd.dll`
* `nvngx_dlss.dll`(DLSS 超分辨率 / 去噪)
* `nvngx_dlssd.dll`(DLSS 光线重建)
* `nvngx_dlssg.dll`(DLSS 帧生成)

#### Linux

从[这个](https://github.com/NVIDIA/DLSS/tree/v310.5.3/lib/Linux_x86_64/rel)路径中下载如下列表中的文件到`.minecraft/radiance`文件夹(如果文件夹不存在,请创建一个)。

* `libnvidia-ngx-dlss.so.310.5.3`
* `libnvidia-ngx-dlssd.so.310.5.3`
* `libnvidia-ngx-dlss.so.310.5.3`(DLSS 超分辨率 / 去噪)
* `libnvidia-ngx-dlssd.so.310.5.3`(DLSS 光线重建)
* `libnvidia-ngx-dlssg.so.310.5.3`(DLSS 帧生成)

# 构建

Expand All @@ -84,7 +86,9 @@ git clone https://github.com/Minecraft-Radiance/MCVR.git

- [ ] 移植到更多版本和mod加载器(WIP,最高优先级)
- [x] XESS支持
- [ ] 帧生成
- [x] DLSS 帧生成
- [ ] FSR 帧生成
- [ ] XeSS-FG
- [ ] HDR

以及更多...
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@ Note for AMD Users: If the DLSS runtime is missing, download the DLSS runtime li

Download the files listed below from [here](https://github.com/NVIDIA/DLSS/tree/v310.5.3/lib/Windows_x86_64/rel) to the `.minecraft/radiance` folder (if the folder not exist, create one).

* `nvngx_dlss.dll`
* `nvngx_dlssd.dll`
* `nvngx_dlss.dll` (DLSS Super Resolution / Denoising)
* `nvngx_dlssd.dll` (DLSS Ray Reconstruction)
* `nvngx_dlssg.dll` (DLSS Frame Generation)

#### Linux

Download the files listed below from [here](https://github.com/NVIDIA/DLSS/tree/v310.5.3/lib/Linux_x86_64/rel) to the `.minecraft/radiance` folder (if the folder not exist, create one).

* `libnvidia-ngx-dlss.so.310.5.3`
* `libnvidia-ngx-dlssd.so.310.5.3`
* `libnvidia-ngx-dlss.so.310.5.3` (DLSS Super Resolution / Denoising)
* `libnvidia-ngx-dlssd.so.310.5.3` (DLSS Ray Reconstruction)
* `libnvidia-ngx-dlssg.so.310.5.3` (DLSS Frame Generation)

# Build

Expand All @@ -87,7 +89,9 @@ Finally, build with `./gradlew build`.

- [ ] port to more versions and mod loaders (WIP, first priority)
- [x] XESS support
- [ ] Frame Generation
- [x] DLSS Frame Generation
- [ ] FSR Frame Generation
- [ ] XeSS-FG
- [ ] HDR

And more...
Expand Down
53 changes: 37 additions & 16 deletions src/main/java/com/radiance/client/gui/AttributeWidgetUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,16 @@ static int totalWidgetWidth(List<ClickableWidget> widgets, int singleWidth, int
static List<ClickableWidget> buildWidgets(AttributeConfig cfg, TextRenderer textRenderer,
int width,
int vec3ComponentWidth) {
return buildWidgets(cfg, textRenderer, width, vec3ComponentWidth, () -> {});
}

static List<ClickableWidget> buildWidgets(AttributeConfig cfg, TextRenderer textRenderer,
int width,
int vec3ComponentWidth, Runnable onChanged) {
String type = cfg.type == null ? "" : cfg.type.toLowerCase(Locale.ROOT);

if (type.startsWith("enum:")) {
return List.of(buildEnumWidget(cfg, cfg.type.substring(5), width));
return List.of(buildEnumWidget(cfg, cfg.type.substring(5), width, onChanged));
}

if (type.startsWith("int_range:")) {
Expand All @@ -100,26 +106,29 @@ static List<ClickableWidget> buildWidgets(AttributeConfig cfg, TextRenderer text
}

return switch (type) {
case "bool" -> List.of(buildBoolWidget(cfg, width));
case "int" -> List.of(buildIntWidget(cfg, textRenderer, width));
case "float" -> List.of(buildFloatWidget(cfg, textRenderer, width));
case "string" -> List.of(buildStringWidget(cfg, textRenderer, width));
case "vec3" -> buildVec3Widget(cfg, textRenderer, vec3ComponentWidth);
default -> List.of(buildStringWidget(cfg, textRenderer, width));
case "bool" -> List.of(buildBoolWidget(cfg, width, onChanged));
case "int" -> List.of(buildIntWidget(cfg, textRenderer, width, onChanged));
case "float" -> List.of(buildFloatWidget(cfg, textRenderer, width, onChanged));
case "string" -> List.of(buildStringWidget(cfg, textRenderer, width, onChanged));
case "vec3" -> buildVec3Widget(cfg, textRenderer, vec3ComponentWidth, onChanged);
default -> List.of(buildStringWidget(cfg, textRenderer, width, onChanged));
};
}

private static ClickableWidget buildBoolWidget(AttributeConfig cfg, int width) {
private static ClickableWidget buildBoolWidget(AttributeConfig cfg, int width,
Runnable onChanged) {
boolean b = "render_pipeline.true".equalsIgnoreCase(cfg.value);
return ButtonWidget.builder(
Text.translatable(b ? "render_pipeline.true" : "render_pipeline.false"), btn -> {
boolean nv = !"render_pipeline.true".equalsIgnoreCase(cfg.value);
cfg.value = nv ? "render_pipeline.true" : "render_pipeline.false";
btn.setMessage(Text.translatable(cfg.value));
onChanged.run();
}).dimensions(0, 0, width, 20).build();
}

private static ClickableWidget buildEnumWidget(AttributeConfig cfg, String raw, int width) {
private static ClickableWidget buildEnumWidget(AttributeConfig cfg, String raw, int width,
Runnable onChanged) {
String[] values = raw.isEmpty() ? new String[]{"<empty>"} : raw.split("-");
int idx = 0;
if (cfg.value != null) {
Expand All @@ -138,25 +147,27 @@ private static ClickableWidget buildEnumWidget(AttributeConfig cfg, String raw,
index[0] = (index[0] + 1) % values.length;
cfg.value = values[index[0]];
btn.setMessage(Text.translatable(cfg.value));
onChanged.run();
}).dimensions(0, 0, width, 20).build();
}

private static ClickableWidget buildIntWidget(AttributeConfig cfg, TextRenderer textRenderer,
int width) {
int width, Runnable onChanged) {
TextFieldWidget tf = new TextFieldWidget(textRenderer, 0, 0, width, 20, Text.empty());
tf.setMaxLength(64);
tf.setText(cfg.value == null ? "" : cfg.value);
tf.setTextPredicate(s -> s.isEmpty() || s.equals("-") || s.matches("-?\\d+"));
tf.setChangedListener(text -> {
if (isStrictInt(text)) {
cfg.value = text;
onChanged.run();
}
});
return tf;
}

private static ClickableWidget buildFloatWidget(AttributeConfig cfg, TextRenderer textRenderer,
int width) {
int width, Runnable onChanged) {
TextFieldWidget tf = new TextFieldWidget(textRenderer, 0, 0, width, 20, Text.empty());
tf.setMaxLength(64);
tf.setText(cfg.value == null ? "" : cfg.value);
Expand All @@ -167,23 +178,28 @@ private static ClickableWidget buildFloatWidget(AttributeConfig cfg, TextRendere
tf.setChangedListener(text -> {
if (isStrictFloat(text)) {
cfg.value = text;
onChanged.run();
}
});
return tf;
}

private static ClickableWidget buildStringWidget(AttributeConfig cfg, TextRenderer textRenderer,
int width) {
private static ClickableWidget buildStringWidget(AttributeConfig cfg,
TextRenderer textRenderer,
int width, Runnable onChanged) {
TextFieldWidget tf = new TextFieldWidget(textRenderer, 0, 0, width, 20, Text.empty());
tf.setMaxLength(128);
tf.setText(cfg.value == null ? "" : cfg.value);
tf.setChangedListener(text -> cfg.value = text);
tf.setChangedListener(text -> {
cfg.value = text;
onChanged.run();
});
return tf;
}

private static List<ClickableWidget> buildVec3Widget(AttributeConfig cfg,
TextRenderer textRenderer,
int componentWidth) {
int componentWidth, Runnable onChanged) {
if (cfg.value == null || cfg.value.isEmpty()) {
cfg.value = "0,0,0";
}
Expand All @@ -200,14 +216,19 @@ private static List<ClickableWidget> buildVec3Widget(AttributeConfig cfg,

if (isStrictFloat(sx) && isStrictFloat(sy) && isStrictFloat(sz)) {
cfg.value = sx + "," + sy + "," + sz;
onChanged.run();
}
};

x.setChangedListener(s -> syncIfValid.run());
y.setChangedListener(s -> syncIfValid.run());
z.setChangedListener(s -> syncIfValid.run());

syncIfValid.run();
// Normalize initial value without firing onChanged
String sx0 = x.getText(), sy0 = y.getText(), sz0 = z.getText();
if (isStrictFloat(sx0) && isStrictFloat(sy0) && isStrictFloat(sz0)) {
cfg.value = sx0 + "," + sy0 + "," + sz0;
}
return List.of(x, y, z);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ protected void init() {

for (AttributeConfig cfg : list) {
List<ClickableWidget> ws = AttributeWidgetUtil.buildWidgets(cfg, textRenderer, WIDGET_WIDTH,
VEC3_COMPONENT_WIDTH);
VEC3_COMPONENT_WIDTH, () -> {});
for (ClickableWidget w : ws) {
addDrawableChild(w);
}
Expand Down
31 changes: 19 additions & 12 deletions src/main/java/com/radiance/client/gui/RenderPipelineScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class RenderPipelineScreen extends Screen {
private boolean isPanning = false;

private Mode mode = Mode.PIPELINE;
private boolean isDirty = false;
private final List<PresetEntry> presets = new ArrayList<>();
private PresetEntry activePreset = null;
private PresetSelector activePresetSelector = null;
Expand Down Expand Up @@ -144,6 +145,7 @@ private void rebuildUI() {
Pipeline.switchToPipelineMode();
mode = Mode.PIPELINE;
}
isDirty = false;
rebuildUI();
}).dimensions(toggleX, 6, toggleW, 20).build());

Expand Down Expand Up @@ -180,6 +182,7 @@ private void rebuildUI() {
} else {
syncPresetToPipeline();
}
isDirty = false;
}).dimensions(secondaryX + secondaryW + 5, 6, 100, 20).build());

ButtonWidget reloadBtn = addDrawableChild(
Expand All @@ -189,6 +192,7 @@ private void rebuildUI() {
} else {
applyActivePreset();
}
isDirty = false;
}).dimensions(secondaryX + secondaryW + 110, 6, 100, 20).build());

saveBtn.active = true;
Expand All @@ -201,15 +205,16 @@ private void rebuildUI() {
if (activePreset == null && !presets.isEmpty()) {
activePreset = presets.get(0);
}
Pipeline.switchToPresetMode(activePreset != null ? activePreset.name() : "Default");
applyActivePreset();
}
}

public void refreshPipeline() {
nodes.clear();
for (Module module : Pipeline.INSTANCE.getModules()) {
nodes.add(new ModuleNode(module));
ModuleNode node = new ModuleNode(module);
node.updateWidth(textRenderer);
nodes.add(node);
}

moduleConnections.clear();
Expand Down Expand Up @@ -242,20 +247,18 @@ public void syncToPipeline() {

@Override
public void close() {
if (mode == Mode.PIPELINE) {
syncToPipeline();
} else {
syncPresetToPipeline();
if (isDirty) {
if (mode == Mode.PIPELINE) {
syncToPipeline();
} else {
syncPresetToPipeline();
}
}
MinecraftClient.getInstance().setScreen(parent);
}

@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
for (ModuleNode node : nodes) {
node.updateWidth(textRenderer);
}

this.renderBackground(context, mouseX, mouseY, delta);

context.getMatrices().push();
Expand Down Expand Up @@ -471,7 +474,7 @@ private void drawModuleNode(DrawContext context, ModuleNode moduleNode) {
context.drawTexture(RenderLayer::getGuiTextured, GEAR_TEX, gearX, btnY, 0, 0, btnSize,
btnSize, btnSize, btnSize);

context.drawTextWithShadow(textRenderer, "×", deleteX + 3, btnY + 2, 0xFFFF5A5A);
context.drawTextWithShadow(textRenderer, "×", deleteX + 3, btnY + 2, 0xFFFF5A5A);

for (int i = 0; i < moduleNode.rows(); i++) {
int ry = y + moduleNode.headerH + moduleNode.pad + i * moduleNode.rowH + 7;
Expand Down Expand Up @@ -557,6 +560,7 @@ private void handleLocalConnection(ImageConfig current, boolean isOutput) {
if (!testCycle(src, dst)) {
moduleConnections.removeIf(link -> link.dst == dst);
moduleConnections.add(new ModuleConnection(src, dst));
isDirty = true;
}
}
pendingPort = null;
Expand Down Expand Up @@ -610,6 +614,7 @@ private ImageConfig getClickedPort(ModuleNode node, double mouseX, double mouseY
}

private void deleteNode(ModuleNode node) {
isDirty = true;
nodes.remove(node);
moduleConnections.removeIf(
link -> link.src.owner == node.module || link.dst.owner == node.module);
Expand Down Expand Up @@ -661,6 +666,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
}

if (button == 0 && isGearClicked(node, mouseX, mouseY)) {
isDirty = true;
MinecraftClient.getInstance()
.setScreen(new ModuleAttributeScreen(this, node.module));
return true;
Expand Down Expand Up @@ -864,6 +870,7 @@ public boolean onClick(double mouseX, double mouseY) {
module.x = 100;
module.y = 100;
nodes.add(new ModuleNode(module));
isDirty = true;
return true;
}
return false;
Expand Down Expand Up @@ -948,7 +955,7 @@ private void syncPresetToPipeline() {
}

private List<ClickableWidget> buildPresetWidgets(AttributeConfig cfg) {
return AttributeWidgetUtil.buildWidgets(cfg, textRenderer, 200, 64);
return AttributeWidgetUtil.buildWidgets(cfg, textRenderer, 200, 64, () -> isDirty = true);
}

private class PresetSelector {
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/radiance/client/option/DLSSMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@
import static com.radiance.client.option.Options.DLSS_MODE_DLAA;
import static com.radiance.client.option.Options.DLSS_MODE_PERFORMANCE;
import static com.radiance.client.option.Options.DLSS_MODE_QUALITY;
import static com.radiance.client.option.Options.DLSS_MODE_ULTRA_PERFORMANCE;

import com.mojang.serialization.Codec;
import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.TranslatableOption;

public enum DLSSMode implements TranslatableOption, StringIdentifiable {
PERFORMANCE(0, "performance", DLSS_MODE_PERFORMANCE),
BALANCED(1, "balanced", DLSS_MODE_BALANCED),
QUALITY(2, "quality", DLSS_MODE_QUALITY),
DLAA(3, "dlaa", DLSS_MODE_DLAA);
ULTRA_PERFORMANCE(0, "ultra_performance", DLSS_MODE_ULTRA_PERFORMANCE),
PERFORMANCE(1, "performance", DLSS_MODE_PERFORMANCE),
BALANCED(2, "balanced", DLSS_MODE_BALANCED),
QUALITY(3, "quality", DLSS_MODE_QUALITY),
DLAA(4, "dlaa", DLSS_MODE_DLAA);

public static final Codec<DLSSMode> Codec = StringIdentifiable.createCodec(DLSSMode::values);
private final int ordinal;
Expand Down
Loading