diff --git a/common/src/main/java/foundry/veil/api/client/render/light/data/SpotLightData.java b/common/src/main/java/foundry/veil/api/client/render/light/data/SpotLightData.java index 037d10b96..78d7bed88 100644 --- a/common/src/main/java/foundry/veil/api/client/render/light/data/SpotLightData.java +++ b/common/src/main/java/foundry/veil/api/client/render/light/data/SpotLightData.java @@ -1,11 +1,14 @@ package foundry.veil.api.client.render.light.data; +import com.mojang.blaze3d.vertex.VertexConsumer; import foundry.veil.api.client.color.Colorc; import foundry.veil.api.client.editor.EditorAttributeProvider; import foundry.veil.api.client.registry.LightTypeRegistry; import foundry.veil.api.client.render.CullFrustum; +import foundry.veil.api.client.render.MatrixStack; import foundry.veil.api.client.render.light.DDALightData; import foundry.veil.api.client.render.light.InstancedLightData; +import foundry.veil.api.client.render.light.LightGuideProvider; import imgui.ImGui; import net.minecraft.client.Camera; import net.minecraft.util.Mth; @@ -20,7 +23,7 @@ * * @since 4.4.0 */ -public class SpotLightData extends LightData implements InstancedLightData, DDALightData, EditorAttributeProvider { +public class SpotLightData extends LightData implements InstancedLightData, DDALightData, EditorAttributeProvider, LightGuideProvider { private static final float MAX_ANGLE_SIZE = (float) (65535.0 / 2.0 / Math.PI); @@ -33,6 +36,7 @@ public class SpotLightData extends LightData implements InstancedLightData, DDAL protected float angle; protected float distance; protected boolean occlusionEnabled; + protected float inscattering; public SpotLightData() { this.matrix = new Matrix4d(); @@ -44,6 +48,7 @@ public SpotLightData() { this.angle = (float) Math.toRadians(45); this.distance = 1.0F; this.occlusionEnabled = false; + this.inscattering = 0.0F; } @Override @@ -111,6 +116,14 @@ public boolean isOcclusionEnabled() { return this.occlusionEnabled; } + /** + * @return The strength of the light's in-scattering effect. + * @since 4.4.0 + */ + public float getInscatteringStrength() { + return this.inscattering; + } + /** * Sets the size of the light's surface * @@ -150,6 +163,15 @@ public SpotLightData setOcclusionEnabled(boolean occlusionEnabled) { return this; } + /** + * @since 4.4.0 + * */ + public SpotLightData setInscatteringStrength(float inscattering) { + this.inscattering = inscattering; + this.markDirty(); + return this; + } + @Override public SpotLightData setColor(Vector3fc color) { super.setColor(color); @@ -195,6 +217,7 @@ public void store(ByteBuffer buffer) { buffer.position(buffer.position() + 2); // Padding buffer.putFloat(this.distance); buffer.putFloat(this.occlusionEnabled ? 1.0F : 0.0F); + buffer.putFloat(this.inscattering); } @Override @@ -235,6 +258,8 @@ public void renderImGuiAttributes() { float[] editAngle = new float[]{this.angle}; float[] editDistance = new float[]{this.distance}; + float[] editInscattering = new float[]{this.inscattering}; + if (ImGui.sliderAngle("size", editSize, 0.1F, 180.0F, "%.1f")) { this.setSize(editSize[0]); } @@ -294,5 +319,40 @@ public void renderImGuiAttributes() { this.occlusionEnabled = !this.occlusionEnabled; this.markDirty(); } + + if (ImGui.dragScalar("In-scattering", editInscattering, 0.01F, 0.0F)) { + this.setInscatteringStrength(editInscattering[0]); + } + } + + @Override + public void renderLightGuide(MatrixStack stack, VertexConsumer consumer) { + stack.matrixPush(); + + stack.translate(this.position.x, this.position.y, this.position.z); + Vector3f rot = this.orientation.getEulerAnglesXYZ(new Vector3f()).mul(-1); + stack.rotate(new Quaternionf().rotateX(rot.x).rotateLocalY(rot.y).rotateLocalZ(rot.z)); + + Matrix4f pose = stack.position(); + + float radius = this.distance * (float) Math.tan(this.size); + + for (int i = -8; i < 25; i++) { + float x = (float) Math.sin(i / (float) 32 * Mth.TWO_PI) * radius; + float y = (float) Math.cos(i / (float) 32 * Mth.TWO_PI) * radius; + consumer.addVertex(pose, x, y, this.distance).setColor(this.color.red(), this.color.green(), this.color.blue(), this.color.alpha()); + } + + int spokes = 8; + for (int i = 0; i < spokes; i++) { + float theta = i / (float) spokes * Mth.TWO_PI; + float x = (float) Math.sin(theta) * radius; + float y = (float) Math.cos(theta) * radius; + + consumer.addVertex(pose, 0, 0, 0).setColor(this.color.red(), this.color.green(), this.color.blue(), this.color.alpha()); + consumer.addVertex(pose, x, y, this.distance).setColor(this.color.red(), this.color.green(), this.color.blue(), this.color.alpha()); + } + + stack.matrixPop(); } } diff --git a/common/src/main/resources/assets/veil/pinwheel/rendertypes/light/inscattering/spot.json b/common/src/main/resources/assets/veil/pinwheel/rendertypes/light/inscattering/spot.json new file mode 100644 index 000000000..942a551b1 --- /dev/null +++ b/common/src/main/resources/assets/veil/pinwheel/rendertypes/light/inscattering/spot.json @@ -0,0 +1,26 @@ +{ + "format": "POSITION_TEX", + "mode": "QUADS", + "bufferSize": "TRANSIENT", + "sort": false, + "affectsCrumbling": false, + "outline": false, + "layers": [ + { + "type": "veil:shader", + "name": "veil:light/inscattering/spot" + }, + { + "type": "minecraft:write_mask", + "depth": false + }, + { + "type": "minecraft:depth_test", + "mode": "notequal" + }, + { + "type": "minecraft:transparency", + "mode": "additive" + } + ] +} \ No newline at end of file diff --git a/wiki/Lights.md b/wiki/Lights.md index 843592607..38cc6c0a2 100644 --- a/wiki/Lights.md +++ b/wiki/Lights.md @@ -15,6 +15,9 @@ Area lights emit light from a quad, which can be rotated to face any direction. ### [Directional Lights](https://github.com/FoundryMC/Veil/blob/1.21/common/src/main/java/foundry/veil/api/client/render/light/data/DirectionalLightData.java) Directional lights, unlike point and area lights, do not have a position, merely having a `direction` property. Directional lights simulate the sun, shadowing faces away from the light. +### [Spot Lights](https://github.com/FoundryMC/Veil/blob/1.21/common/src/main/java/foundry/veil/api/client/render/light/data/SpotLightData.java) +Spot lights emit light from a point, which can be rotated to face any direction. Spot lights have the same values as Area lights except it has one `size` value instead of separate width and height values. + ## Light Renderers Each light type additionally its own [`LightTypeRenderer`](https://github.com/FoundryMC/Veil/blob/1.21/common/src/main/java/foundry/veil/api/client/render/light/renderer/LightTypeRenderer.java). Each `LightTypeRenderer` is responsible for rendering all lights of its assigned types. Lights that have a position (like point and area lights) can extend the [`InstancedLightRenderer`](https://github.com/FoundryMC/Veil/blob/1.21/common/src/main/java/foundry/veil/api/client/render/light/renderer/InstancedLightRenderer.java) to have some methods built in.