первый коммит, мусор в 3д текстуре
This commit is contained in:
10
src/client/java/su/divan2000/veila/client/VeilaClient.java
Normal file
10
src/client/java/su/divan2000/veila/client/VeilaClient.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package su.divan2000.veila.client;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
|
||||
public class VeilaClient implements ClientModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package su.divan2000.veila.client;
|
||||
|
||||
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
|
||||
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
|
||||
|
||||
public class VeilaDataGenerator implements DataGeneratorEntrypoint {
|
||||
|
||||
@Override
|
||||
public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
|
||||
FabricDataGenerator.Pack pack = fabricDataGenerator.createPack();
|
||||
}
|
||||
}
|
||||
111
src/client/java/su/divan2000/veila/client/gl/DepthCopy.java
Normal file
111
src/client/java/su/divan2000/veila/client/gl/DepthCopy.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package su.divan2000.veila.client.gl;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class DepthCopy {
|
||||
|
||||
private static int texture = -1;
|
||||
|
||||
private static int width = -1;
|
||||
private static int height = -1;
|
||||
|
||||
|
||||
public static void init(int newWidth, int newHeight) {
|
||||
|
||||
if (texture != -1 &&
|
||||
width == newWidth &&
|
||||
height == newHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (texture != -1) {
|
||||
GL11.glDeleteTextures(texture);
|
||||
}
|
||||
|
||||
|
||||
texture = GL11.glGenTextures();
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
texture
|
||||
);
|
||||
|
||||
|
||||
GL11.glTexImage2D(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
0,
|
||||
GL30.GL_DEPTH_COMPONENT32F,
|
||||
newWidth,
|
||||
newHeight,
|
||||
0,
|
||||
GL11.GL_DEPTH_COMPONENT,
|
||||
GL11.GL_FLOAT,
|
||||
(ByteBuffer)null
|
||||
);
|
||||
|
||||
|
||||
GL11.glTexParameteri(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
GL11.GL_TEXTURE_MIN_FILTER,
|
||||
GL11.GL_NEAREST
|
||||
);
|
||||
|
||||
GL11.glTexParameteri(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
GL11.GL_TEXTURE_MAG_FILTER,
|
||||
GL11.GL_NEAREST
|
||||
);
|
||||
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
0
|
||||
);
|
||||
|
||||
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
|
||||
|
||||
System.out.println(
|
||||
"Depth texture resized: "
|
||||
+ width + "x" + height
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static void copy(int width, int height) {
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
texture
|
||||
);
|
||||
|
||||
|
||||
GL11.glCopyTexSubImage2D(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height
|
||||
);
|
||||
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static int getTexture() {
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package su.divan2000.veila.client.gl;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.glGetInteger;
|
||||
import static org.lwjgl.opengl.GL30.GL_VERTEX_ARRAY_BINDING;
|
||||
|
||||
public final class FullscreenQuad {
|
||||
|
||||
private static int vao = 0;
|
||||
private static int vbo = 0;
|
||||
|
||||
public static void init() {
|
||||
|
||||
if (vao != 0)
|
||||
return;
|
||||
|
||||
float[] vertices = {
|
||||
-1f, -1f,
|
||||
1f, -1f,
|
||||
1f, 1f,
|
||||
|
||||
-1f, -1f,
|
||||
1f, 1f,
|
||||
-1f, 1f
|
||||
};
|
||||
|
||||
FloatBuffer buffer = BufferUtils.createFloatBuffer(vertices.length);
|
||||
buffer.put(vertices);
|
||||
buffer.flip();
|
||||
|
||||
vao = GL30.glGenVertexArrays();
|
||||
vbo = GL15.glGenBuffers();
|
||||
|
||||
int previous = glGetInteger(GL_VERTEX_ARRAY_BINDING);
|
||||
|
||||
GL30.glBindVertexArray(vao);
|
||||
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
|
||||
|
||||
GL20.glEnableVertexAttribArray(0);
|
||||
GL20.glVertexAttribPointer(
|
||||
0,
|
||||
2,
|
||||
GL11.GL_FLOAT,
|
||||
false,
|
||||
2 * Float.BYTES,
|
||||
0
|
||||
);
|
||||
|
||||
GL30.glBindVertexArray(previous);
|
||||
}
|
||||
|
||||
public static void draw() {
|
||||
|
||||
int previous = glGetInteger(GL_VERTEX_ARRAY_BINDING);
|
||||
|
||||
GL30.glBindVertexArray(vao);
|
||||
|
||||
GL11.glDrawArrays(
|
||||
GL11.GL_TRIANGLES,
|
||||
0,
|
||||
6
|
||||
);
|
||||
|
||||
GL30.glBindVertexArray(previous);
|
||||
}
|
||||
}
|
||||
55
src/client/java/su/divan2000/veila/client/gl/GLProgram.java
Normal file
55
src/client/java/su/divan2000/veila/client/gl/GLProgram.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package su.divan2000.veila.client.gl;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
public class GLProgram {
|
||||
|
||||
private final int id;
|
||||
|
||||
public GLProgram(GLShader vertex, GLShader fragment) {
|
||||
|
||||
id = GL20.glCreateProgram();
|
||||
|
||||
GL20.glBindAttribLocation(id, 0, "aPos");
|
||||
|
||||
GL20.glAttachShader(id, vertex.id());
|
||||
GL20.glAttachShader(id, fragment.id());
|
||||
|
||||
GL20.glLinkProgram(id);
|
||||
|
||||
if (GL20.glGetProgrami(id, GL20.GL_LINK_STATUS) == GL20.GL_FALSE) {
|
||||
throw new RuntimeException(
|
||||
"Program link failed:\n" +
|
||||
GL20.glGetProgramInfoLog(id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
GL20.glUseProgram(id);
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
GL20.glUseProgram(0);
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
GL20.glDeleteProgram(id);
|
||||
}
|
||||
|
||||
public int uniform(String name) {
|
||||
return GL20.glGetUniformLocation(id, name);
|
||||
}
|
||||
|
||||
public void uniform1i(String name, int value) {
|
||||
GL20.glUniform1i(uniform(name), value);
|
||||
}
|
||||
|
||||
public void uniform1f(String name, float value) {
|
||||
GL20.glUniform1f(uniform(name), value);
|
||||
}
|
||||
}
|
||||
30
src/client/java/su/divan2000/veila/client/gl/GLShader.java
Normal file
30
src/client/java/su/divan2000/veila/client/gl/GLShader.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package su.divan2000.veila.client.gl;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
public class GLShader {
|
||||
|
||||
private final int id;
|
||||
|
||||
public GLShader(int type, String source) {
|
||||
id = GL20.glCreateShader(type);
|
||||
|
||||
GL20.glShaderSource(id, source);
|
||||
GL20.glCompileShader(id);
|
||||
|
||||
if (GL20.glGetShaderi(id, GL20.GL_COMPILE_STATUS) == GL20.GL_FALSE) {
|
||||
throw new RuntimeException(
|
||||
"Shader compile failed:\n" +
|
||||
GL20.glGetShaderInfoLog(id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
GL20.glDeleteShader(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package su.divan2000.veila.client.gl;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public final class ResourceUtil {
|
||||
|
||||
private ResourceUtil() {
|
||||
}
|
||||
|
||||
public static String load(String path) {
|
||||
|
||||
Identifier id = new Identifier("veila", path);
|
||||
|
||||
try {
|
||||
Resource resource = MinecraftClient.getInstance()
|
||||
.getResourceManager()
|
||||
.getResource(id)
|
||||
.orElseThrow();
|
||||
|
||||
try (InputStream in = resource.getInputStream()) {
|
||||
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Cannot load shader " + id, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package su.divan2000.veila.client.render;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gl.Framebuffer;
|
||||
import net.minecraft.client.render.Camera;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.*;
|
||||
import su.divan2000.veila.client.gl.DepthCopy;
|
||||
import su.divan2000.veila.client.gl.FullscreenQuad;
|
||||
import su.divan2000.veila.client.gl.GLProgram;
|
||||
import su.divan2000.veila.client.gl.GLShader;
|
||||
import su.divan2000.veila.client.gl.ResourceUtil;
|
||||
import su.divan2000.veila.client.render.fog.FogSystem;
|
||||
import su.divan2000.veila.client.render.fog.FogWorldVolume;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
public class PostProcessingManager {
|
||||
|
||||
private static GLProgram program;
|
||||
|
||||
/*
|
||||
* Матрицы
|
||||
*/
|
||||
|
||||
private static final Matrix4f projection = new Matrix4f();
|
||||
private static final Matrix4f inverseProjection = new Matrix4f();
|
||||
|
||||
private static final FloatBuffer projectionBuffer =
|
||||
BufferUtils.createFloatBuffer(16);
|
||||
|
||||
private static final FloatBuffer inverseProjectionBuffer =
|
||||
BufferUtils.createFloatBuffer(16);
|
||||
|
||||
/*
|
||||
* Uniform locations
|
||||
*/
|
||||
|
||||
private static int projectionLocation;
|
||||
private static int inverseProjectionLocation;
|
||||
|
||||
private static int diffuseSamplerLocation;
|
||||
private static int depthSamplerLocation;
|
||||
|
||||
private static int cameraPositionLocation;
|
||||
private static int screenSizeLocation;
|
||||
|
||||
private static final Matrix4f view = new Matrix4f();
|
||||
private static final Matrix4f inverseView = new Matrix4f();
|
||||
|
||||
private static final FloatBuffer viewBuffer =
|
||||
BufferUtils.createFloatBuffer(16);
|
||||
|
||||
private static final FloatBuffer inverseViewBuffer =
|
||||
BufferUtils.createFloatBuffer(16);
|
||||
|
||||
private static int viewLocation;
|
||||
private static int inverseViewLocation;
|
||||
|
||||
private static int fogVolumeLocation;
|
||||
private static int fogOriginLocation;
|
||||
|
||||
private static int ringOffsetLocation;
|
||||
|
||||
public static void init() {
|
||||
|
||||
if (program != null)
|
||||
return;
|
||||
|
||||
GLShader vertex = new GLShader(
|
||||
GL20.GL_VERTEX_SHADER,
|
||||
ResourceUtil.load("shaders/fullscreen.vert")
|
||||
);
|
||||
|
||||
GLShader fragment = new GLShader(
|
||||
GL20.GL_FRAGMENT_SHADER,
|
||||
ResourceUtil.load("shaders/red.frag")
|
||||
);
|
||||
|
||||
program = new GLProgram(vertex, fragment);
|
||||
|
||||
projectionLocation = program.uniform("Projection");
|
||||
inverseProjectionLocation = program.uniform("InverseProjection");
|
||||
|
||||
diffuseSamplerLocation = program.uniform("DiffuseSampler");
|
||||
depthSamplerLocation = program.uniform("DepthSampler");
|
||||
|
||||
fogVolumeLocation = program.uniform("FogVolume");
|
||||
fogOriginLocation = program.uniform("FogOrigin");
|
||||
ringOffsetLocation = program.uniform("RingBlockOffset");
|
||||
|
||||
cameraPositionLocation = program.uniform("CameraPosition");
|
||||
screenSizeLocation = program.uniform("ScreenSize");
|
||||
|
||||
viewLocation = program.uniform("View");
|
||||
inverseViewLocation = program.uniform("InverseView");
|
||||
|
||||
FullscreenQuad.init();
|
||||
|
||||
vertex.delete();
|
||||
fragment.delete();
|
||||
|
||||
System.out.println("VEILA shader compiled!");
|
||||
}
|
||||
|
||||
public static void render() {
|
||||
|
||||
if (program == null)
|
||||
return;
|
||||
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
Framebuffer framebuffer = client.getFramebuffer();
|
||||
|
||||
int width = framebuffer.textureWidth;
|
||||
int height = framebuffer.textureHeight;
|
||||
|
||||
GL30.glBindFramebuffer(
|
||||
GL30.GL_READ_FRAMEBUFFER,
|
||||
framebuffer.fbo
|
||||
);
|
||||
|
||||
DepthCopy.init(width, height);
|
||||
DepthCopy.copy(width, height);
|
||||
|
||||
program.bind();
|
||||
|
||||
/*
|
||||
* Diffuse
|
||||
*/
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GL11.glBindTexture(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
framebuffer.getColorAttachment()
|
||||
);
|
||||
GL20.glUniform1i(diffuseSamplerLocation, 0);
|
||||
|
||||
/*
|
||||
* Depth
|
||||
*/
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GL11.glBindTexture(
|
||||
GL11.GL_TEXTURE_2D,
|
||||
DepthCopy.getTexture()
|
||||
);
|
||||
GL20.glUniform1i(depthSamplerLocation, 1);
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE2);
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
FogWorldVolume.getTexture()
|
||||
);
|
||||
|
||||
GL20.glUniform1i(
|
||||
fogVolumeLocation,
|
||||
2
|
||||
);
|
||||
|
||||
GL20.glUniform2i(
|
||||
fogOriginLocation,
|
||||
FogSystem.originChunkX() * FogWorldVolume.CHUNK_SIZE,
|
||||
FogSystem.originChunkZ() * FogWorldVolume.CHUNK_SIZE
|
||||
);
|
||||
|
||||
GL20.glUniform2i(
|
||||
ringOffsetLocation,
|
||||
FogSystem.ringChunkOffsetX() * FogWorldVolume.CHUNK_SIZE,
|
||||
FogSystem.ringChunkOffsetZ() * FogWorldVolume.CHUNK_SIZE
|
||||
);
|
||||
|
||||
/*
|
||||
* Матрицы
|
||||
*/
|
||||
|
||||
updateProjectionMatrices();
|
||||
|
||||
GL20.glUniformMatrix4fv(
|
||||
projectionLocation,
|
||||
false,
|
||||
projectionBuffer
|
||||
);
|
||||
|
||||
GL20.glUniformMatrix4fv(
|
||||
inverseProjectionLocation,
|
||||
false,
|
||||
inverseProjectionBuffer
|
||||
);
|
||||
|
||||
GL20.glUniformMatrix4fv(
|
||||
viewLocation,
|
||||
false,
|
||||
viewBuffer
|
||||
);
|
||||
|
||||
GL20.glUniformMatrix4fv(
|
||||
inverseViewLocation,
|
||||
false,
|
||||
inverseViewBuffer
|
||||
);
|
||||
|
||||
/*
|
||||
* Камера
|
||||
*/
|
||||
|
||||
Camera camera = client.gameRenderer.getCamera();
|
||||
Vec3d pos = camera.getPos();
|
||||
|
||||
GL20.glUniform3f(
|
||||
cameraPositionLocation,
|
||||
(float) pos.x,
|
||||
(float) pos.y,
|
||||
(float) pos.z
|
||||
);
|
||||
|
||||
/*
|
||||
* Размер экрана
|
||||
*/
|
||||
|
||||
GL20.glUniform2f(
|
||||
screenSizeLocation,
|
||||
width,
|
||||
height
|
||||
);
|
||||
|
||||
FullscreenQuad.draw();
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE2);
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
|
||||
program.unbind();
|
||||
|
||||
GL30.glBindFramebuffer(
|
||||
GL30.GL_READ_FRAMEBUFFER,
|
||||
0
|
||||
);
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
}
|
||||
|
||||
private static void updateProjectionMatrices() {
|
||||
|
||||
projection.set(RenderSystem.getProjectionMatrix());
|
||||
|
||||
inverseProjection
|
||||
.set(projection)
|
||||
.invert();
|
||||
|
||||
projectionBuffer.clear();
|
||||
projection.get(projectionBuffer);
|
||||
|
||||
inverseProjectionBuffer.clear();
|
||||
inverseProjection.get(inverseProjectionBuffer);
|
||||
}
|
||||
|
||||
public static void updateViewMatrix(Matrix4f matrix) {
|
||||
|
||||
view.set(matrix);
|
||||
|
||||
inverseView
|
||||
.set(matrix)
|
||||
.invert();
|
||||
|
||||
viewBuffer.clear();
|
||||
view.get(viewBuffer);
|
||||
|
||||
inverseViewBuffer.clear();
|
||||
inverseView.get(inverseViewBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package su.divan2000.veila.client.render.fog;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
public final class FogChunkProvider {
|
||||
static void fillChunk(
|
||||
int chunkX,
|
||||
int chunkZ,
|
||||
FloatBuffer buffer
|
||||
) {
|
||||
|
||||
float density =
|
||||
hash(chunkX, chunkZ);
|
||||
|
||||
for (int z = 0;
|
||||
z < FogWorldVolume.CHUNK_SIZE;
|
||||
z++) {
|
||||
|
||||
for (int y = 0;
|
||||
y < FogWorldVolume.SIZE_Y;
|
||||
y++) {
|
||||
|
||||
int worldY =
|
||||
FogWorldVolume.MIN_Y + y;
|
||||
|
||||
float value =
|
||||
worldY < 70
|
||||
? density
|
||||
: 0.0f;
|
||||
|
||||
for (int x = 0;
|
||||
x < FogWorldVolume.CHUNK_SIZE;
|
||||
x++) {
|
||||
|
||||
buffer.put(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static float hash(
|
||||
int x,
|
||||
int z
|
||||
) {
|
||||
|
||||
int h = x * 73428767;
|
||||
|
||||
h ^= z * 912931;
|
||||
|
||||
h ^= h >> 13;
|
||||
|
||||
h *= 1274126177;
|
||||
|
||||
return ((h >>> 24) & 255)
|
||||
/ 255.0f
|
||||
* 0.08f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package su.divan2000.veila.client.render.fog;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static su.divan2000.veila.client.render.fog.FogWorldVolume.CHUNK_SIZE;
|
||||
import static su.divan2000.veila.client.render.fog.FogWorldVolume.SIZE_Y;
|
||||
|
||||
public final class FogChunkStreamer {
|
||||
|
||||
private FogChunkStreamer() {
|
||||
}
|
||||
|
||||
public static void update(
|
||||
int oldOriginChunkX,
|
||||
int oldOriginChunkZ,
|
||||
int newOriginChunkX,
|
||||
int newOriginChunkZ
|
||||
) {
|
||||
|
||||
int dx = newOriginChunkX - oldOriginChunkX;
|
||||
int dz = newOriginChunkZ - oldOriginChunkZ;
|
||||
|
||||
/*
|
||||
* Телепорт.
|
||||
*/
|
||||
|
||||
if (Math.abs(dx) >= FogWorldVolume.CHUNKS_X ||
|
||||
Math.abs(dz) >= FogWorldVolume.CHUNKS_Z) {
|
||||
|
||||
refillAll(
|
||||
newOriginChunkX,
|
||||
newOriginChunkZ
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Новые колонки.
|
||||
*/
|
||||
|
||||
if (dx > 0) {
|
||||
|
||||
for (int i = 0; i < dx; i++) {
|
||||
|
||||
uploadColumn(
|
||||
newOriginChunkX +
|
||||
FogWorldVolume.CHUNKS_X - dx + i,
|
||||
newOriginChunkZ
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (dx < 0) {
|
||||
|
||||
for (int i = 0; i < -dx; i++) {
|
||||
|
||||
uploadColumn(
|
||||
newOriginChunkX + i,
|
||||
newOriginChunkZ
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Новые строки.
|
||||
*/
|
||||
|
||||
if (dz > 0) {
|
||||
|
||||
for (int i = 0; i < dz; i++) {
|
||||
|
||||
uploadRow(
|
||||
newOriginChunkX,
|
||||
newOriginChunkZ +
|
||||
FogWorldVolume.CHUNKS_Z - dz + i
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (dz < 0) {
|
||||
|
||||
for (int i = 0; i < -dz; i++) {
|
||||
|
||||
uploadRow(
|
||||
newOriginChunkX,
|
||||
newOriginChunkZ + i
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void refillAll(
|
||||
int originChunkX,
|
||||
int originChunkZ
|
||||
) {
|
||||
|
||||
for (int z = 0; z < FogWorldVolume.CHUNKS_Z; z++) {
|
||||
|
||||
for (int x = 0; x < FogWorldVolume.CHUNKS_X; x++) {
|
||||
|
||||
uploadChunk(
|
||||
originChunkX + x,
|
||||
originChunkZ + z
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void uploadColumn(
|
||||
int worldChunkX,
|
||||
int originChunkZ
|
||||
) {
|
||||
|
||||
for (int z = 0; z < FogWorldVolume.CHUNKS_Z; z++) {
|
||||
|
||||
uploadChunk(
|
||||
worldChunkX,
|
||||
originChunkZ + z
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void uploadRow(
|
||||
int originChunkX,
|
||||
int worldChunkZ
|
||||
) {
|
||||
|
||||
for (int x = 0; x < FogWorldVolume.CHUNKS_X; x++) {
|
||||
|
||||
uploadChunk(
|
||||
originChunkX + x,
|
||||
worldChunkZ
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void uploadChunk(
|
||||
int worldChunkX,
|
||||
int worldChunkZ
|
||||
) {
|
||||
|
||||
FloatBuffer buffer =
|
||||
FogWorldVolume.chunkBuffer();
|
||||
|
||||
FogChunkProvider.fillChunk(
|
||||
worldChunkX,
|
||||
worldChunkZ,
|
||||
buffer
|
||||
);
|
||||
|
||||
buffer.flip();
|
||||
|
||||
int physicalChunkX =
|
||||
Math.floorMod(
|
||||
worldChunkX,
|
||||
FogWorldVolume.CHUNKS_X
|
||||
);
|
||||
|
||||
int physicalChunkZ =
|
||||
Math.floorMod(
|
||||
worldChunkZ,
|
||||
FogWorldVolume.CHUNKS_Z
|
||||
);
|
||||
|
||||
|
||||
System.out.println(
|
||||
worldChunkX + " " +
|
||||
worldChunkZ + " -> " +
|
||||
physicalChunkX + " " +
|
||||
physicalChunkZ
|
||||
);
|
||||
|
||||
|
||||
FogWorldVolume.uploadChunk(
|
||||
physicalChunkX,
|
||||
physicalChunkZ,
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package su.divan2000.veila.client.render.fog;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
public final class FogSystem {
|
||||
|
||||
private static boolean initialized;
|
||||
|
||||
private static int originChunkX;
|
||||
private static int originChunkZ;
|
||||
|
||||
private static int ringChunkOffsetX;
|
||||
private static int ringChunkOffsetZ;
|
||||
|
||||
private FogSystem() {
|
||||
}
|
||||
|
||||
/*
|
||||
* Вызывается в начале render()
|
||||
*
|
||||
* Только Render Thread.
|
||||
*/
|
||||
|
||||
public static void beginRender() {
|
||||
|
||||
if (!initialized) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
updateWindow();
|
||||
}
|
||||
|
||||
/*
|
||||
* Вызывается каждый client tick.
|
||||
*
|
||||
* Пока пусто.
|
||||
*/
|
||||
|
||||
public static void tick() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Инициализация всей системы.
|
||||
*/
|
||||
|
||||
private static void initialize() {
|
||||
|
||||
FogWorldVolume.init();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Пока просто заполняем весь объём
|
||||
* тестовыми чанками.
|
||||
*/
|
||||
|
||||
private static void fillTestVolume() {
|
||||
|
||||
for (int chunkZ = 0;
|
||||
chunkZ < FogWorldVolume.CHUNKS_Z;
|
||||
chunkZ++) {
|
||||
|
||||
for (int chunkX = 0;
|
||||
chunkX < FogWorldVolume.CHUNKS_X;
|
||||
chunkX++) {
|
||||
|
||||
FloatBuffer buffer =
|
||||
FogWorldVolume.chunkBuffer();
|
||||
|
||||
FogChunkProvider.fillChunk(
|
||||
originChunkX + chunkX,
|
||||
originChunkZ + chunkZ,
|
||||
buffer
|
||||
);
|
||||
|
||||
buffer.flip();
|
||||
|
||||
FogWorldVolume.uploadChunk(
|
||||
chunkX,
|
||||
chunkZ,
|
||||
buffer
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateWindow() {
|
||||
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
if (client.world == null || client.player == null)
|
||||
return;
|
||||
|
||||
int playerChunkX = client.player.getBlockX() >> 4;
|
||||
int playerChunkZ = client.player.getBlockZ() >> 4;
|
||||
|
||||
int newOriginChunkX =
|
||||
playerChunkX - FogWorldVolume.CHUNKS_X / 2;
|
||||
|
||||
int newOriginChunkZ =
|
||||
playerChunkZ - FogWorldVolume.CHUNKS_Z / 2;
|
||||
|
||||
if (newOriginChunkX == originChunkX &&
|
||||
newOriginChunkZ == originChunkZ)
|
||||
return;
|
||||
|
||||
int oldOriginChunkX = originChunkX;
|
||||
int oldOriginChunkZ = originChunkZ;
|
||||
|
||||
originChunkX = newOriginChunkX;
|
||||
originChunkZ = newOriginChunkZ;
|
||||
|
||||
FogChunkStreamer.update(
|
||||
oldOriginChunkX,
|
||||
oldOriginChunkZ,
|
||||
originChunkX,
|
||||
originChunkZ
|
||||
);
|
||||
|
||||
ringChunkOffsetX =
|
||||
Math.floorMod(originChunkX,
|
||||
FogWorldVolume.CHUNKS_X);
|
||||
|
||||
ringChunkOffsetZ =
|
||||
Math.floorMod(originChunkZ,
|
||||
FogWorldVolume.CHUNKS_Z);
|
||||
}
|
||||
|
||||
public static int originChunkX() {
|
||||
return originChunkX;
|
||||
}
|
||||
|
||||
public static int originChunkZ() {
|
||||
return originChunkZ;
|
||||
}
|
||||
|
||||
public static int ringChunkOffsetX() {
|
||||
return ringChunkOffsetX;
|
||||
}
|
||||
|
||||
public static int ringChunkOffsetZ() {
|
||||
return ringChunkOffsetZ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package su.divan2000.veila.client.render.fog;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
public final class FogWorldVolume {
|
||||
|
||||
/*
|
||||
* Размер всего объёма
|
||||
*/
|
||||
|
||||
public static final int SIZE_X = 256;
|
||||
public static final int SIZE_Z = 256;
|
||||
|
||||
public static final int MIN_Y = -64;
|
||||
public static final int MAX_Y = 320;
|
||||
public static final int SIZE_Y = MAX_Y - MIN_Y;
|
||||
|
||||
/*
|
||||
* Размер одного чанка
|
||||
*/
|
||||
|
||||
public static final int CHUNK_SIZE = 16;
|
||||
|
||||
public static final int CHUNKS_X = SIZE_X / CHUNK_SIZE;
|
||||
public static final int CHUNKS_Z = SIZE_Z / CHUNK_SIZE;
|
||||
|
||||
/*
|
||||
* OpenGL
|
||||
*/
|
||||
|
||||
private static int texture = -1;
|
||||
|
||||
/*
|
||||
* Буфер для одного чанка
|
||||
*
|
||||
* 16 × 384 × 16
|
||||
*/
|
||||
|
||||
private static final FloatBuffer CHUNK_BUFFER =
|
||||
BufferUtils.createFloatBuffer(
|
||||
CHUNK_SIZE *
|
||||
SIZE_Y *
|
||||
CHUNK_SIZE
|
||||
);
|
||||
|
||||
private FogWorldVolume() {
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
||||
if (texture != -1)
|
||||
return;
|
||||
|
||||
texture = GL11.glGenTextures();
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
texture
|
||||
);
|
||||
|
||||
GL30.glTexImage3D(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
0,
|
||||
GL30.GL_R16F,
|
||||
SIZE_X,
|
||||
SIZE_Y,
|
||||
SIZE_Z,
|
||||
0,
|
||||
GL11.GL_RED,
|
||||
GL11.GL_FLOAT,
|
||||
(ByteBuffer) null
|
||||
);
|
||||
|
||||
GL11.glTexParameteri(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
GL11.GL_TEXTURE_MIN_FILTER,
|
||||
GL11.GL_LINEAR
|
||||
);
|
||||
|
||||
GL11.glTexParameteri(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
GL11.GL_TEXTURE_MAG_FILTER,
|
||||
GL11.GL_LINEAR
|
||||
);
|
||||
|
||||
GL11.glTexParameteri(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
GL12.GL_TEXTURE_WRAP_S,
|
||||
GL12.GL_CLAMP_TO_EDGE
|
||||
);
|
||||
|
||||
GL11.glTexParameteri(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
GL12.GL_TEXTURE_WRAP_T,
|
||||
GL12.GL_CLAMP_TO_EDGE
|
||||
);
|
||||
|
||||
GL11.glTexParameteri(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
GL12.GL_TEXTURE_WRAP_R,
|
||||
GL12.GL_CLAMP_TO_EDGE
|
||||
);
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
0
|
||||
);
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
|
||||
CHUNK_BUFFER.clear();
|
||||
|
||||
int size =
|
||||
CHUNK_SIZE *
|
||||
SIZE_Y *
|
||||
CHUNK_SIZE;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
CHUNK_BUFFER.put(0.0f);
|
||||
|
||||
CHUNK_BUFFER.flip();
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
texture
|
||||
);
|
||||
|
||||
for (int chunkZ = 0; chunkZ < CHUNKS_Z; chunkZ++) {
|
||||
|
||||
for (int chunkX = 0; chunkX < CHUNKS_X; chunkX++) {
|
||||
|
||||
uploadChunk(
|
||||
chunkX,
|
||||
chunkZ,
|
||||
CHUNK_BUFFER
|
||||
);
|
||||
|
||||
CHUNK_BUFFER.rewind();
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glBindTexture(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
public static void uploadChunk(
|
||||
int textureChunkX,
|
||||
int textureChunkZ,
|
||||
FloatBuffer data
|
||||
) {
|
||||
|
||||
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, texture);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
System.out.println(
|
||||
data.remaining()
|
||||
);
|
||||
|
||||
|
||||
int error = GL11.glGetError();
|
||||
|
||||
if (error != GL11.GL_NO_ERROR) {
|
||||
System.out.println("GL BEFORE = " + error);
|
||||
}
|
||||
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
0,
|
||||
|
||||
textureChunkX * CHUNK_SIZE,
|
||||
0,
|
||||
textureChunkZ * CHUNK_SIZE,
|
||||
|
||||
CHUNK_SIZE,
|
||||
SIZE_Y,
|
||||
CHUNK_SIZE,
|
||||
|
||||
GL11.GL_RED,
|
||||
GL11.GL_FLOAT,
|
||||
data
|
||||
);
|
||||
|
||||
error = GL11.glGetError();
|
||||
|
||||
if (error != GL11.GL_NO_ERROR) {
|
||||
System.out.println("GL AFTER = " + error);
|
||||
}
|
||||
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
}
|
||||
|
||||
public static FloatBuffer chunkBuffer() {
|
||||
|
||||
CHUNK_BUFFER.clear();
|
||||
|
||||
return CHUNK_BUFFER;
|
||||
}
|
||||
|
||||
public static int getTexture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package su.divan2000.veila.mixin.client;
|
||||
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.joml.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 su.divan2000.veila.client.render.PostProcessingManager;
|
||||
import su.divan2000.veila.client.render.fog.FogSystem;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class GameRendererMixin {
|
||||
|
||||
@Inject(
|
||||
method = "renderWorld",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lcom/mojang/blaze3d/systems/RenderSystem;clear(IZ)V"
|
||||
)
|
||||
)
|
||||
private void veila$postProcess(
|
||||
float tickDelta,
|
||||
long limitTime,
|
||||
MatrixStack matrices,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
PostProcessingManager.init();
|
||||
PostProcessingManager.render();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "renderWorld",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target =
|
||||
"Lnet/minecraft/client/render/WorldRenderer;render(Lnet/minecraft/client/util/math/MatrixStack;FJZLnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/GameRenderer;Lnet/minecraft/client/render/LightmapTextureManager;Lorg/joml/Matrix4f;)V"
|
||||
)
|
||||
)
|
||||
private void veila$captureView(
|
||||
float tickDelta,
|
||||
long limitTime,
|
||||
MatrixStack matrices,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
PostProcessingManager.updateViewMatrix(
|
||||
new Matrix4f(
|
||||
matrices.peek().getPositionMatrix()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "render",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void veila$beginRender(
|
||||
float tickDelta,
|
||||
long startTime,
|
||||
boolean tick,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
FogSystem.beginRender();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package su.divan2000.veila.mixin.client;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
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 su.divan2000.veila.client.render.fog.FogSystem;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public class MinecraftClientMixin {
|
||||
|
||||
@Inject(
|
||||
method = "tick",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void veila$fogTick(CallbackInfo ci) {
|
||||
FogSystem.tick();
|
||||
}
|
||||
}
|
||||
11
src/client/resources/assets/veila/shaders/fullscreen.vert
Normal file
11
src/client/resources/assets/veila/shaders/fullscreen.vert
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 150
|
||||
|
||||
in vec2 aPos;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
texCoord = aPos * 0.5 + 0.5;
|
||||
gl_Position = vec4(aPos, 0.0, 1.0);
|
||||
}
|
||||
137
src/client/resources/assets/veila/shaders/red.frag
Normal file
137
src/client/resources/assets/veila/shaders/red.frag
Normal file
@@ -0,0 +1,137 @@
|
||||
#version 150
|
||||
|
||||
uniform sampler2D DiffuseSampler;
|
||||
uniform sampler2D DepthSampler;
|
||||
uniform sampler3D FogVolume;
|
||||
|
||||
uniform mat4 InverseProjection;
|
||||
uniform mat4 InverseView;
|
||||
|
||||
uniform vec3 CameraPosition;
|
||||
|
||||
uniform ivec2 FogOrigin;
|
||||
uniform ivec2 RingBlockOffset;
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Настройки
|
||||
//------------------------------------------------------------
|
||||
|
||||
const float STEP_SIZE = 0.5;
|
||||
const float MAX_DISTANCE = 256.0;
|
||||
const int MAX_STEPS = int(MAX_DISTANCE / STEP_SIZE);
|
||||
|
||||
// Размер туманного объёма
|
||||
const float FOG_SIZE_X = 256.0;
|
||||
const float FOG_SIZE_Z = 256.0;
|
||||
|
||||
// Высота мира
|
||||
const float WORLD_BOTTOM = -64.0;
|
||||
const float WORLD_HEIGHT = 384.0;
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
vec3 reconstructViewPosition(vec2 uv)
|
||||
{
|
||||
float depth = texture(DepthSampler, uv).r;
|
||||
|
||||
vec4 clip = vec4(
|
||||
uv * 2.0 - 1.0,
|
||||
depth * 2.0 - 1.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
vec4 view = InverseProjection * clip;
|
||||
|
||||
return view.xyz / view.w;
|
||||
}
|
||||
|
||||
vec3 reconstructWorldPosition(vec2 uv)
|
||||
{
|
||||
vec3 viewPos = reconstructViewPosition(uv);
|
||||
|
||||
vec4 world = InverseView * vec4(viewPos, 1.0);
|
||||
|
||||
return world.xyz + CameraPosition;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
float density(vec3 worldPos)
|
||||
{
|
||||
vec3 uv;
|
||||
|
||||
float localX = worldPos.x - float(FogOrigin.x);
|
||||
float localZ = worldPos.z - float(FogOrigin.y);
|
||||
|
||||
if (
|
||||
localX < 0.0 || localX >= FOG_SIZE_X ||
|
||||
localZ < 0.0 || localZ >= FOG_SIZE_Z ||
|
||||
worldPos.y < WORLD_BOTTOM ||
|
||||
worldPos.y >= WORLD_BOTTOM + WORLD_HEIGHT
|
||||
){
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
float physicalX = mod(
|
||||
localX + float(RingBlockOffset.x),
|
||||
FOG_SIZE_X
|
||||
);
|
||||
|
||||
float physicalZ = mod(
|
||||
localZ + float(RingBlockOffset.y),
|
||||
FOG_SIZE_Z
|
||||
);
|
||||
|
||||
uv.x = physicalX / FOG_SIZE_X;
|
||||
uv.z = physicalZ / FOG_SIZE_Z;
|
||||
uv.y = (worldPos.y - WORLD_BOTTOM) / WORLD_HEIGHT;
|
||||
|
||||
return texture(FogVolume, uv).r;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 sceneColor = texture(DiffuseSampler, texCoord);
|
||||
|
||||
vec3 worldPos = reconstructWorldPosition(texCoord);
|
||||
|
||||
vec3 rayDir = normalize(worldPos - CameraPosition);
|
||||
|
||||
float rayLength = distance(worldPos, CameraPosition);
|
||||
rayLength = min(rayLength, MAX_DISTANCE);
|
||||
|
||||
vec3 samplePos = CameraPosition;
|
||||
|
||||
float fog = 0.0;
|
||||
|
||||
for (int i = 0; i < MAX_STEPS; i++)
|
||||
{
|
||||
float traveled = float(i) * STEP_SIZE;
|
||||
|
||||
if (traveled >= rayLength)
|
||||
break;
|
||||
|
||||
samplePos += rayDir * STEP_SIZE;
|
||||
|
||||
fog += density(samplePos) * STEP_SIZE;
|
||||
}
|
||||
|
||||
fog = clamp(fog, 0.0, 1.0);
|
||||
|
||||
vec3 fogColor = vec3(
|
||||
0.75,
|
||||
0.80,
|
||||
0.90
|
||||
);
|
||||
|
||||
FragColor = vec4(
|
||||
mix(sceneColor.rgb, fogColor, fog),
|
||||
1.0
|
||||
);
|
||||
}
|
||||
16
src/client/resources/veila.client.mixins.json
Normal file
16
src/client/resources/veila.client.mixins.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "su.divan2000.veila.mixin.client",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"client": [
|
||||
"GameRendererMixin",
|
||||
"MinecraftClientMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"overwrites": {
|
||||
"requireAnnotations": true
|
||||
}
|
||||
}
|
||||
10
src/main/java/su/divan2000/veila/Veila.java
Normal file
10
src/main/java/su/divan2000/veila/Veila.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package su.divan2000.veila;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
|
||||
public class Veila implements ModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
}
|
||||
}
|
||||
34
src/main/resources/fabric.mod.json
Normal file
34
src/main/resources/fabric.mod.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "veila",
|
||||
"version": "${version}",
|
||||
|
||||
"name": "Veila",
|
||||
"description": "",
|
||||
"authors": [],
|
||||
"contact": {},
|
||||
|
||||
"license": "GPL-3.0",
|
||||
"icon": "assets/veila/icon.png",
|
||||
|
||||
"environment": "client",
|
||||
"entrypoints": {
|
||||
"fabric-datagen": ["su.divan2000.veila.client.VeilaDataGenerator"],
|
||||
"client": ["su.divan2000.veila.client.VeilaClient"],
|
||||
"main": ["su.divan2000.veila.Veila"]
|
||||
},
|
||||
|
||||
"mixins": [
|
||||
"veila.mixins.json"
|
||||
,{
|
||||
"config": "veila.client.mixins.json",
|
||||
"environment": "client"
|
||||
}
|
||||
],
|
||||
|
||||
"depends": {
|
||||
"fabricloader": ">=${loader_version}",
|
||||
"fabric-api": "*",
|
||||
"minecraft": "${minecraft_version}"
|
||||
}
|
||||
}
|
||||
14
src/main/resources/veila.mixins.json
Normal file
14
src/main/resources/veila.mixins.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "su.divan2000.veila.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"overwrites": {
|
||||
"requireAnnotations": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user