mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-15 18:13:48 +01:00
correct contraption lighting
This commit is contained in:
parent
7443ac5031
commit
876ddde660
10 changed files with 173 additions and 68 deletions
|
@ -78,6 +78,7 @@ public class ClientEvents {
|
|||
return;
|
||||
|
||||
CreateClient.kineticRenderer.tick();
|
||||
FastContraptionRenderer.tick();
|
||||
|
||||
CreateClient.schematicSender.tick();
|
||||
CreateClient.schematicAndQuillHandler.tick();
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
package com.simibubi.create.foundation.utility.render;
|
||||
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.LightType;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.lighting.WorldLightManager;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
import org.lwjgl.opengl.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
|
@ -27,6 +28,8 @@ public class ContraptionLighter {
|
|||
|
||||
ByteBuffer lightVolume;
|
||||
|
||||
boolean dirty;
|
||||
|
||||
int texture;
|
||||
|
||||
public ContraptionLighter(Contraption contraption) {
|
||||
|
@ -34,53 +37,114 @@ public class ContraptionLighter {
|
|||
|
||||
AxisAlignedBB bounds = contraption.bounds;
|
||||
|
||||
int minX = (int) Math.floor(bounds.minX);
|
||||
int minY = (int) Math.floor(bounds.minY);
|
||||
int minZ = (int) Math.floor(bounds.minZ);
|
||||
int maxX = (int) Math.ceil(bounds.maxX);
|
||||
int maxY = (int) Math.ceil(bounds.maxY);
|
||||
int maxZ = (int) Math.ceil(bounds.maxZ);
|
||||
int minX = (int) Math.floor(bounds.minX) - 1;
|
||||
int minY = (int) Math.floor(bounds.minY) - 1;
|
||||
int minZ = (int) Math.floor(bounds.minZ) - 1;
|
||||
int maxX = (int) Math.ceil(bounds.maxX) + 1;
|
||||
int maxY = (int) Math.ceil(bounds.maxY) + 1;
|
||||
int maxZ = (int) Math.ceil(bounds.maxZ) + 1;
|
||||
|
||||
sizeX = maxX - minX;
|
||||
sizeY = maxY - minY;
|
||||
sizeZ = maxZ - minZ;
|
||||
sizeX = nextPowerOf2(maxX - minX);
|
||||
sizeY = nextPowerOf2(maxY - minY);
|
||||
sizeZ = nextPowerOf2(maxZ - minZ);
|
||||
|
||||
lightVolume = GLAllocation.createDirectByteBuffer(sizeX * sizeY * sizeZ * 2);
|
||||
|
||||
tick(contraption);
|
||||
}
|
||||
|
||||
public static int nextPowerOf2(int a) {
|
||||
int h = Integer.highestOneBit(a);
|
||||
return (h == a) ? h : (h << 1);
|
||||
}
|
||||
|
||||
public int getSizeX() {
|
||||
return sizeX;
|
||||
}
|
||||
|
||||
public int getSizeY() {
|
||||
return sizeY;
|
||||
}
|
||||
|
||||
public int getSizeZ() {
|
||||
return sizeZ;
|
||||
}
|
||||
|
||||
public int getMinX() {
|
||||
return minX;
|
||||
}
|
||||
|
||||
public int getMinY() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
public int getMinZ() {
|
||||
return minZ;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
GL11.glDeleteTextures(texture);
|
||||
CreateClient.kineticRenderer.enqueue(() -> {
|
||||
GL15.glDeleteTextures(texture);
|
||||
});
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
|
||||
private void setupPosition(Contraption c) {
|
||||
Vec3d positionVec = c.entity.getPositionVec();
|
||||
minX = (int) (Math.floor(positionVec.x) - sizeX / 2);
|
||||
minY = (int) (Math.floor(positionVec.y));
|
||||
minZ = (int) (Math.floor(positionVec.z) - sizeZ / 2);
|
||||
}
|
||||
|
||||
public void addLightData(World world, BlockPos pos) {
|
||||
public void tick(Contraption c) {
|
||||
setupPosition(c);
|
||||
|
||||
int contraptionX = pos.getX() - minX;
|
||||
int contraptionY = pos.getY() - minY;
|
||||
int contraptionZ = pos.getZ() - minZ;
|
||||
World world = c.entity.world;
|
||||
|
||||
if (contraptionX < 0 || contraptionX >= sizeX || contraptionY < 0 || contraptionY >= sizeY || contraptionZ < 0 || contraptionZ >= sizeZ)
|
||||
return;
|
||||
BlockPos.Mutable pos = new BlockPos.Mutable();
|
||||
|
||||
int blockLight = world.getLightLevel(LightType.BLOCK, pos);
|
||||
int skyLight = world.getLightLevel(LightType.SKY, pos);
|
||||
for (int x = 0; x < sizeX; x++) {
|
||||
for (int y = 0; y < sizeY; y++) {
|
||||
for (int z = 0; z < sizeZ; z++) {
|
||||
pos.setPos(minX + x, minY + y, minZ + z);
|
||||
|
||||
writeLight(contraptionX, contraptionY, contraptionZ, blockLight, skyLight);
|
||||
int blockLight = world.getLightLevel(LightType.BLOCK, pos);
|
||||
int skyLight = world.getLightLevel(LightType.SKY, pos);
|
||||
|
||||
writeLight(x, y, z, blockLight, skyLight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
private void writeLight(int x, int y, int z, int block, int sky) {
|
||||
int i = (x + y * sizeX + z * sizeX * sizeY) * 2;
|
||||
int i = (x + sizeX * (y + z * sizeY)) * 2;
|
||||
|
||||
lightVolume.put(i, (byte) (block * 16));
|
||||
lightVolume.put(i + 1, (byte) (sky * 16));
|
||||
byte b = (byte) ((block & 0xF) << 4);
|
||||
byte s = (byte) ((sky & 0xF) << 4);
|
||||
|
||||
lightVolume.put(i, b);
|
||||
lightVolume.put(i + 1, s);
|
||||
}
|
||||
|
||||
public void use() {
|
||||
GL13.glEnable(GL31.GL_TEXTURE_3D);
|
||||
GL13.glActiveTexture(GL40.GL_TEXTURE0 + 4);
|
||||
GL12.glBindTexture(GL12.GL_TEXTURE_3D, texture);
|
||||
lightVolume.rewind();
|
||||
GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, GL40.GL_RG, sizeX, sizeY, sizeZ, 0, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, lightVolume);
|
||||
if (dirty) {
|
||||
GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, GL40.GL_RG8, sizeX, sizeY, sizeZ, 0, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, lightVolume);
|
||||
dirty = false;
|
||||
}
|
||||
GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR);
|
||||
GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR);
|
||||
GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP);
|
||||
GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_R, GL13.GL_CLAMP);
|
||||
GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP);
|
||||
}
|
||||
|
||||
public void release() {
|
||||
GL13.glActiveTexture(GL40.GL_TEXTURE0 + 4);
|
||||
GL12.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,18 +14,20 @@ import net.minecraft.client.renderer.color.BlockColors;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class FastContraptionRenderer extends ContraptionRenderer {
|
||||
|
||||
private static final Cache<Integer, FastContraptionRenderer> renderers = CacheBuilder.newBuilder().build();
|
||||
private static final HashMap<Integer, FastContraptionRenderer> renderers = new HashMap<>();
|
||||
|
||||
private ArrayList<ContraptionBuffer> renderLayers = new ArrayList<>();
|
||||
|
||||
|
@ -43,33 +45,48 @@ public class FastContraptionRenderer extends ContraptionRenderer {
|
|||
buildLayers();
|
||||
}
|
||||
|
||||
public static void tick() {
|
||||
if (Minecraft.getInstance().isGamePaused()) return;
|
||||
|
||||
CreateClient.kineticRenderer.enqueue(() -> {
|
||||
for (FastContraptionRenderer renderer : renderers.values()) {
|
||||
renderer.lighter.tick(renderer.c);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setRenderSettings(Vec3d position, Vec3d rotation) {
|
||||
renderPos = position;
|
||||
renderRot = rotation;
|
||||
}
|
||||
|
||||
private void render(int shader) {
|
||||
// GL13.glActiveTexture(GL40.GL_TEXTURE2);
|
||||
// lighter.use();
|
||||
|
||||
int cSize = GlStateManager.getUniformLocation(shader, "cSize");
|
||||
int cPos = GlStateManager.getUniformLocation(shader, "cPos");
|
||||
int cRot = GlStateManager.getUniformLocation(shader, "cRot");
|
||||
lighter.use();
|
||||
|
||||
FloatBuffer buf = ShaderHelper.VEC3_BUFFER;
|
||||
|
||||
buf.put(0, (float) c.bounds.getXSize());
|
||||
buf.put(1, (float) c.bounds.getYSize());
|
||||
buf.put(2, (float) c.bounds.getZSize());
|
||||
int lightBoxSize = GlStateManager.getUniformLocation(shader, "lightBoxSize");
|
||||
buf.put(0, (float) lighter.getSizeX());
|
||||
buf.put(1, (float) lighter.getSizeY());
|
||||
buf.put(2, (float) lighter.getSizeZ());
|
||||
buf.rewind();
|
||||
GlStateManager.uniform3(cSize, buf);
|
||||
GlStateManager.uniform3(lightBoxSize, buf);
|
||||
|
||||
int lightBoxMin = GlStateManager.getUniformLocation(shader, "lightBoxMin");
|
||||
buf.put(0, (float) lighter.getMinX());
|
||||
buf.put(1, (float) lighter.getMinY());
|
||||
buf.put(2, (float) lighter.getMinZ());
|
||||
buf.rewind();
|
||||
GlStateManager.uniform3(lightBoxMin, buf);
|
||||
|
||||
int cPos = GlStateManager.getUniformLocation(shader, "cPos");
|
||||
buf.put(0, (float) renderPos.x);
|
||||
buf.put(1, (float) renderPos.y);
|
||||
buf.put(2, (float) renderPos.z);
|
||||
buf.rewind();
|
||||
GlStateManager.uniform3(cPos, buf);
|
||||
|
||||
int cRot = GlStateManager.getUniformLocation(shader, "cRot");
|
||||
buf.put(0, (float) renderRot.x);
|
||||
buf.put(1, (float) renderRot.y);
|
||||
buf.put(2, (float) renderRot.z);
|
||||
|
@ -79,6 +96,8 @@ public class FastContraptionRenderer extends ContraptionRenderer {
|
|||
for (ContraptionBuffer layer : renderLayers) {
|
||||
layer.render();
|
||||
}
|
||||
|
||||
lighter.release();
|
||||
}
|
||||
|
||||
private void buildLayers() {
|
||||
|
@ -86,8 +105,7 @@ public class FastContraptionRenderer extends ContraptionRenderer {
|
|||
|
||||
List<RenderType> blockLayers = RenderType.getBlockLayers();
|
||||
|
||||
for (int i = 0; i < blockLayers.size(); i++) {
|
||||
RenderType layer = blockLayers.get(i);
|
||||
for (RenderType layer : blockLayers) {
|
||||
renderLayers.add(buildStructureBuffer(c, layer));
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +114,7 @@ public class FastContraptionRenderer extends ContraptionRenderer {
|
|||
for (ContraptionBuffer buffer : renderLayers) {
|
||||
buffer.invalidate();
|
||||
}
|
||||
lighter.delete();
|
||||
|
||||
renderLayers.clear();
|
||||
}
|
||||
|
@ -105,12 +124,16 @@ public class FastContraptionRenderer extends ContraptionRenderer {
|
|||
}
|
||||
|
||||
private static FastContraptionRenderer getRenderer(World world, Contraption c) {
|
||||
try {
|
||||
return renderers.get(c.entity.getEntityId(), () -> new FastContraptionRenderer(world, c));
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
FastContraptionRenderer renderer;
|
||||
int entityId = c.entity.getEntityId();
|
||||
if (renderers.containsKey(entityId)) {
|
||||
renderer = renderers.get(entityId);
|
||||
} else {
|
||||
renderer = new FastContraptionRenderer(world, c);
|
||||
renderers.put(entityId, renderer);
|
||||
}
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public static void renderAll(RenderWorldLastEvent event) {
|
||||
|
@ -123,7 +146,7 @@ public class FastContraptionRenderer extends ContraptionRenderer {
|
|||
|
||||
ArrayList<Integer> toRemove = new ArrayList<>();
|
||||
|
||||
for (FastContraptionRenderer renderer : renderers.asMap().values()) {
|
||||
for (FastContraptionRenderer renderer : renderers.values()) {
|
||||
if (renderer.c.entity.isAlive())
|
||||
renderer.render(shader);
|
||||
else
|
||||
|
@ -134,15 +157,17 @@ public class FastContraptionRenderer extends ContraptionRenderer {
|
|||
|
||||
CreateClient.kineticRenderer.teardown();
|
||||
|
||||
renderers.invalidateAll(toRemove);
|
||||
for (Integer id : toRemove) {
|
||||
renderers.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
public static void invalidateAll() {
|
||||
for (FastContraptionRenderer renderer : renderers.asMap().values()) {
|
||||
for (FastContraptionRenderer renderer : renderers.values()) {
|
||||
renderer.invalidate();
|
||||
}
|
||||
|
||||
renderers.invalidateAll();
|
||||
renderers.clear();
|
||||
}
|
||||
|
||||
private static ContraptionBuffer buildStructureBuffer(Contraption c, RenderType layer) {
|
||||
|
|
|
@ -124,7 +124,7 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
|||
GL30.glBindVertexArray(vao);
|
||||
finishBuffering();
|
||||
|
||||
int numAttributes = getInstanceFormat().getNumAttributes() + 3;
|
||||
int numAttributes = getInstanceFormat().getNumAttributes() + FORMAT.getNumAttributes();
|
||||
for (int i = 0; i <= numAttributes; i++) {
|
||||
GL40.glEnableVertexAttribArray(i);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.simibubi.create.foundation.utility.render.shader;
|
|||
public enum Shader {
|
||||
ROTATING_INSTANCED("shader/rotating.vert", "shader/instanced.frag"),
|
||||
BELT_INSTANCED("shader/belt.vert", "shader/instanced.frag"),
|
||||
CONTRAPTION_STRUCTURE("shader/contraption_static.vert", "shader/instanced.frag"),
|
||||
CONTRAPTION_STRUCTURE("shader/contraption.vert", "shader/contraption.frag"),
|
||||
;
|
||||
|
||||
public final String vert;
|
||||
|
|
|
@ -15,7 +15,6 @@ layout (location = 9) in float scrollMult;
|
|||
|
||||
out vec2 TexCoords;
|
||||
out vec2 Light;
|
||||
out vec4 Color;
|
||||
out float Diffuse;
|
||||
|
||||
uniform float time;
|
||||
|
@ -54,7 +53,6 @@ void main() {
|
|||
float scroll = fract(speed * time / (36 * 16.)) * scrollSize * scrollMult;
|
||||
|
||||
Diffuse = diffuse(normalize((rotation * vec4(aNormal, 0.)).xyz));
|
||||
Color = vec4(1f);
|
||||
Light = light;
|
||||
TexCoords = aTexCoords - sourceUV + scrollTexture.xy + vec2(0., scroll);
|
||||
gl_Position = projection * view * renderPos;
|
||||
|
|
24
src/main/resources/assets/create/shader/contraption.frag
Normal file
24
src/main/resources/assets/create/shader/contraption.frag
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 440 core
|
||||
|
||||
in vec2 TexCoords;
|
||||
in vec4 Color;
|
||||
in float Diffuse;
|
||||
in vec3 BoxCoord;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
layout(binding=0) uniform sampler2D BlockAtlas;
|
||||
layout(binding=1) uniform sampler2D LightMap;
|
||||
layout(binding=4) uniform sampler3D LightVolume;
|
||||
|
||||
vec4 light() {
|
||||
vec2 lm = texture(LightVolume, BoxCoord).rg * 0.9375 + 0.03125;
|
||||
return texture2D(LightMap, lm);
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 tex = texture2D(BlockAtlas, TexCoords);
|
||||
|
||||
fragColor = vec4(tex.rgb * light().rgb * Diffuse, tex.a);
|
||||
}
|
|
@ -8,12 +8,11 @@ layout (location = 3) in vec4 aColor;
|
|||
|
||||
out float Diffuse;
|
||||
out vec2 TexCoords;
|
||||
out vec2 Light;
|
||||
out vec4 Color;
|
||||
out vec3 BoxCoord;
|
||||
|
||||
layout (binding = 2) uniform sampler3D lightVolume;
|
||||
|
||||
uniform vec3 cSize;
|
||||
uniform vec3 lightBoxSize;
|
||||
uniform vec3 lightBoxMin;
|
||||
uniform vec3 cPos;
|
||||
uniform vec3 cRot;
|
||||
|
||||
|
@ -53,13 +52,13 @@ void main() {
|
|||
|
||||
vec4 worldPos = rotatedPos + vec4(cPos + vec3(0.5), 0);
|
||||
|
||||
vec3 boxCoord = (worldPos.xyz - cPos - cSize * 0.5) / cSize;
|
||||
vec3 boxCoord = (worldPos.xyz - lightBoxMin) / lightBoxSize;
|
||||
|
||||
float df = diffuse(normalize(aNormal));
|
||||
|
||||
Diffuse = diffuse(normalize((rotation * vec4(aNormal, 0.)).xyz));
|
||||
Color = vec4(aColor.rgb / df, aColor.a);
|
||||
Light = vec2(1.);
|
||||
BoxCoord = boxCoord;
|
||||
TexCoords = aTexCoords;
|
||||
gl_Position = projection * view * worldPos;
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
in vec2 TexCoords;
|
||||
in vec2 Light;
|
||||
in vec4 Color;
|
||||
in float Diffuse;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
@ -15,11 +14,8 @@ vec4 light() {
|
|||
return texture2D(LightMap, lm);
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 tex = texture2D(BlockAtlas, TexCoords);
|
||||
|
||||
tex *= vec4(light().rgb * Diffuse, 1);
|
||||
|
||||
fragColor = tex;
|
||||
fragColor = vec4(tex.rgb * light().rgb * Diffuse, tex.a);
|
||||
}
|
|
@ -12,7 +12,6 @@ layout (location = 7) in vec3 rotationAxis;
|
|||
|
||||
out vec2 TexCoords;
|
||||
out vec2 Light;
|
||||
out vec4 Color;
|
||||
out float Diffuse;
|
||||
|
||||
uniform float time;
|
||||
|
@ -48,7 +47,6 @@ void main() {
|
|||
renderPos += vec4(instancePos + vec3(0.5), 0);
|
||||
|
||||
Diffuse = diffuse(normalize((rotation * vec4(aNormal, 0.)).xyz));
|
||||
Color = vec4(1f);
|
||||
TexCoords = aTexCoords;
|
||||
gl_Position = projection * view * renderPos;
|
||||
Light = light;
|
||||
|
|
Loading…
Reference in a new issue