Flywheel/src/main/java/com/jozufozu/flywheel/light/GPULightVolume.java

134 lines
4 KiB
Java
Raw Normal View History

package com.jozufozu.flywheel.light;
import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_S;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_T;
import static org.lwjgl.opengl.GL11.GL_UNPACK_ALIGNMENT;
import static org.lwjgl.opengl.GL11.GL_UNPACK_ROW_LENGTH;
import static org.lwjgl.opengl.GL11.GL_UNPACK_SKIP_PIXELS;
import static org.lwjgl.opengl.GL11.GL_UNPACK_SKIP_ROWS;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL11.glPixelStorei;
import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D;
import static org.lwjgl.opengl.GL12.GL_TEXTURE_WRAP_R;
import static org.lwjgl.opengl.GL12.GL_UNPACK_IMAGE_HEIGHT;
import static org.lwjgl.opengl.GL12.GL_UNPACK_SKIP_IMAGES;
import static org.lwjgl.opengl.GL12.glTexImage3D;
import static org.lwjgl.opengl.GL12.glTexSubImage3D;
import static org.lwjgl.opengl.GL14.GL_MIRRORED_REPEAT;
import org.lwjgl.opengl.GL30;
import com.jozufozu.flywheel.backend.gl.GlTexture;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import net.minecraft.world.level.BlockAndTintGetter;
public class GPULightVolume extends LightVolume {
protected final GridAlignedBB sampleVolume = new GridAlignedBB();
private final GlTexture glTexture;
2021-11-09 23:59:31 +01:00
private final GlTextureUnit textureUnit = GlTextureUnit.T4;
protected boolean bufferDirty;
public GPULightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
super(level, sampleVolume);
this.sampleVolume.assign(sampleVolume);
glTexture = new GlTexture(GL_TEXTURE_3D);
GlTextureUnit oldState = GlTextureUnit.getActive();
// allocate space for the texture
textureUnit.makeActive();
glTexture.bind();
int sizeX = box.sizeX();
int sizeY = box.sizeY();
int sizeZ = box.sizeZ();
glTexImage3D(GL_TEXTURE_3D, 0, GL30.GL_RG8, sizeX, sizeY, sizeZ, 0, GL30.GL_RG, GL_UNSIGNED_BYTE, 0);
glTexture.setParameteri(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexture.setParameteri(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexture.setParameteri(GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexture.setParameteri(GL_TEXTURE_WRAP_R, GL_MIRRORED_REPEAT);
glTexture.setParameteri(GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexture.unbind();
oldState.makeActive();
}
@Override
protected void setBox(ImmutableBox box) {
this.box.assign(box);
this.box.nextPowerOf2Centered();
// called during super ctor
if (sampleVolume != null) this.sampleVolume.assign(box);
}
public void bind() {
// just in case something goes wrong, or we accidentally call this before this volume is properly disposed of.
if (lightData == null || lightData.capacity() == 0) return;
2021-11-09 23:59:31 +01:00
textureUnit.makeActive();
glTexture.bind();
uploadTexture();
}
private void uploadTexture() {
if (bufferDirty) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 2); // we use 2 bytes per texel
int sizeX = box.sizeX();
int sizeY = box.sizeY();
int sizeZ = box.sizeZ();
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, GL30.GL_RG, GL_UNSIGNED_BYTE, lightData);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4 is the default
bufferDirty = false;
}
}
public void unbind() {
glTexture.unbind();
}
@Override
public void delete() {
super.delete();
glTexture.delete();
}
public void move(ImmutableBox newSampleVolume) {
if (lightData == null) return;
if (box.contains(newSampleVolume)) {
sampleVolume.assign(newSampleVolume);
initialize();
} else {
super.move(newSampleVolume);
}
}
@Override
public ImmutableBox getVolume() {
return sampleVolume;
}
@Override
protected void markDirty() {
this.bufferDirty = true;
}
}