mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-02 18:57:10 -04:00
Test how well a sparse 3d texture would work for storing and interpolating light data.
This commit is contained in:
parent
0adfbbc79e
commit
0008d7f1fa
@ -2,6 +2,7 @@
|
||||
|
||||
in vec3 mvVertexPos;
|
||||
in vec3 light;
|
||||
in vec3 chunkPos;
|
||||
flat in int blockType;
|
||||
flat in int faceNormal;
|
||||
flat in int modelIndex;
|
||||
@ -15,6 +16,9 @@ in vec3 direction;
|
||||
|
||||
uniform sampler2DArray texture_sampler;
|
||||
uniform sampler2DArray emissionSampler;
|
||||
uniform uint chunkDataIndex;
|
||||
uniform vec3 ambientLight;
|
||||
uniform int voxelSize;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
@ -31,6 +35,69 @@ layout(std430, binding = 1) buffer _textureData
|
||||
TextureData textureData[];
|
||||
};
|
||||
|
||||
struct ChunkData {
|
||||
uint lightMapPtrs[6*6*6];
|
||||
};
|
||||
|
||||
struct LightData {
|
||||
int values[8*8*8];
|
||||
};
|
||||
|
||||
layout(std430, binding = 7) buffer _chunkData
|
||||
{
|
||||
ChunkData chunkData[];
|
||||
};
|
||||
layout(std430, binding = 8) buffer _lightData
|
||||
{
|
||||
LightData lightData[];
|
||||
};
|
||||
|
||||
vec3 sampleLight(ivec3 pos) {
|
||||
pos += 8;
|
||||
ivec3 rough = pos/8;
|
||||
int roughIndex = (rough.x*6 + rough.y)*6 + rough.z;
|
||||
ivec3 fine = pos&7;
|
||||
int fineIndex = (fine.x*8 + fine.y)*8 + fine.z;
|
||||
int lightValue = lightData[chunkData[chunkDataIndex].lightMapPtrs[roughIndex]].values[fineIndex];
|
||||
vec3 sunLight = vec3(
|
||||
lightValue >> 25 & 31,
|
||||
lightValue >> 20 & 31,
|
||||
lightValue >> 15 & 31
|
||||
);
|
||||
vec3 blockLight = vec3(
|
||||
lightValue >> 10 & 31,
|
||||
lightValue >> 5 & 31,
|
||||
lightValue >> 0 & 31
|
||||
);
|
||||
return max(sunLight*ambientLight, blockLight)/32;
|
||||
}
|
||||
|
||||
vec3 sCurve(vec3 x) {
|
||||
return (3*x - 2*x*x)*x;
|
||||
}
|
||||
|
||||
vec3 getLight(vec3 pos, vec3 normal) {
|
||||
pos += normal/2;
|
||||
pos -= vec3(0.5, 0.5, 0.5);
|
||||
ivec3 start = ivec3(floor(pos));
|
||||
vec3 diff = sCurve(pos - start);
|
||||
vec3 invDiff = 1 - diff;
|
||||
|
||||
vec3 state = vec3(0);
|
||||
for(int dx = 0; dx < 2; dx++) {
|
||||
for(int dy = 0; dy < 2; dy++) {
|
||||
for(int dz = 0; dz < 2; dz++) {
|
||||
ivec3 delta = ivec3(dx, dy, dz);
|
||||
vec3 light = sampleLight(start + delta);
|
||||
bvec3 isOne = bvec3(notEqual(delta, ivec3(0)));
|
||||
vec3 interpolation = mix(invDiff, diff, isOne);
|
||||
state += light*interpolation.x*interpolation.y*interpolation.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
const float[6] normalVariations = float[6](
|
||||
1.0, //vec3(0, 1, 0),
|
||||
@ -40,6 +107,14 @@ const float[6] normalVariations = float[6](
|
||||
0.96, //vec3(0, 0, 1),
|
||||
0.88 //vec3(0, 0, -1)
|
||||
);
|
||||
const vec3[6] normals = vec3[6](
|
||||
vec3(0, 1, 0),
|
||||
vec3(0, -1, 0),
|
||||
vec3(1, 0, 0),
|
||||
vec3(-1, 0, 0),
|
||||
vec3(0, 0, 1),
|
||||
vec3(0, 0, -1)
|
||||
);
|
||||
|
||||
float ditherThresholds[16] = float[16] (
|
||||
1/17.0, 9/17.0, 3/17.0, 11/17.0,
|
||||
@ -82,6 +157,7 @@ void main() {
|
||||
uint textureIndex = textureData[blockType].textureIndices[faceNormal];
|
||||
float normalVariation = normalVariations[faceNormal];
|
||||
vec3 textureCoords = vec3(getTextureCoordsNormal(startPosition/16, faceNormal), textureIndex);
|
||||
vec3 light = getLight(chunkPos + startPosition/16.0/voxelSize, normals[faceNormal]);
|
||||
fragColor = texture(texture_sampler, textureCoords)*vec4(light*normalVariation, 1);
|
||||
|
||||
if(!passDitherTest(fragColor.a)) discard;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
out vec3 mvVertexPos;
|
||||
out vec3 light;
|
||||
out vec3 chunkPos;
|
||||
flat out int blockType;
|
||||
flat out int modelIndex;
|
||||
flat out int faceNormal;
|
||||
@ -22,7 +23,6 @@ uniform vec3 modelPosition;
|
||||
struct FaceData {
|
||||
int encodedPositionAndNormalsAndPermutation;
|
||||
int blockAndModel;
|
||||
int light[4];
|
||||
};
|
||||
layout(std430, binding = 3) buffer _faceData
|
||||
{
|
||||
@ -131,18 +131,7 @@ void main() {
|
||||
int vertexID = gl_VertexID%4;
|
||||
int encodedPositionAndNormalsAndPermutation = faceData[faceID].encodedPositionAndNormalsAndPermutation;
|
||||
int blockAndModel = faceData[faceID].blockAndModel;
|
||||
int fullLight = faceData[faceID].light[vertexID];
|
||||
vec3 sunLight = vec3(
|
||||
fullLight >> 25 & 31,
|
||||
fullLight >> 20 & 31,
|
||||
fullLight >> 15 & 31
|
||||
);
|
||||
vec3 blockLight = vec3(
|
||||
fullLight >> 10 & 31,
|
||||
fullLight >> 5 & 31,
|
||||
fullLight >> 0 & 31
|
||||
);
|
||||
light = max(sunLight*ambientLight, blockLight)/32;
|
||||
light = vec3(1, 1, 1);
|
||||
isBackFace = encodedPositionAndNormalsAndPermutation>>19 & 1;
|
||||
int oldNormal = (encodedPositionAndNormalsAndPermutation >> 20) & 7;
|
||||
mat3 permutationMatrix = permutationMatrices[(encodedPositionAndNormalsAndPermutation >> 23) & 7];
|
||||
@ -158,6 +147,7 @@ void main() {
|
||||
encodedPositionAndNormalsAndPermutation >> 5 & 31,
|
||||
encodedPositionAndNormalsAndPermutation >> 10 & 31
|
||||
);
|
||||
chunkPos = vec3(position) - normals[normal];
|
||||
int octantIndex = (position.x >> 4) | (position.y >> 4)<<1 | (position.z >> 4)<<2;
|
||||
if((visibilityMask & 1<<octantIndex) == 0) { // discard face
|
||||
gl_Position = vec4(-2, -2, -2, 1);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
in vec3 mvVertexPos;
|
||||
in vec3 light;
|
||||
in vec3 chunkPos;
|
||||
flat in int blockType;
|
||||
flat in int faceNormal;
|
||||
flat in int modelIndex;
|
||||
@ -16,6 +17,9 @@ uniform sampler2DArray texture_sampler;
|
||||
uniform sampler2DArray emissionSampler;
|
||||
uniform samplerCube reflectionMap;
|
||||
uniform float reflectionMapSize;
|
||||
uniform uint chunkDataIndex;
|
||||
uniform vec3 ambientLight;
|
||||
uniform int voxelSize;
|
||||
|
||||
layout(binding = 3) uniform sampler2D depthTexture;
|
||||
|
||||
@ -40,6 +44,69 @@ layout(std430, binding = 1) buffer _textureData
|
||||
TextureData textureData[];
|
||||
};
|
||||
|
||||
struct ChunkData {
|
||||
uint lightMapPtrs[6*6*6];
|
||||
};
|
||||
|
||||
struct LightData {
|
||||
int values[8*8*8];
|
||||
};
|
||||
|
||||
layout(std430, binding = 7) buffer _chunkData
|
||||
{
|
||||
ChunkData chunkData[];
|
||||
};
|
||||
layout(std430, binding = 8) buffer _lightData
|
||||
{
|
||||
LightData lightData[];
|
||||
};
|
||||
|
||||
vec3 sampleLight(ivec3 pos) {
|
||||
pos += 8;
|
||||
ivec3 rough = pos/8;
|
||||
int roughIndex = (rough.x*6 + rough.y)*6 + rough.z;
|
||||
ivec3 fine = pos&7;
|
||||
int fineIndex = (fine.x*8 + fine.y)*8 + fine.z;
|
||||
int lightValue = lightData[chunkData[chunkDataIndex].lightMapPtrs[roughIndex]].values[fineIndex];
|
||||
vec3 sunLight = vec3(
|
||||
lightValue >> 25 & 31,
|
||||
lightValue >> 20 & 31,
|
||||
lightValue >> 15 & 31
|
||||
);
|
||||
vec3 blockLight = vec3(
|
||||
lightValue >> 10 & 31,
|
||||
lightValue >> 5 & 31,
|
||||
lightValue >> 0 & 31
|
||||
);
|
||||
return max(sunLight*ambientLight, blockLight)/32;
|
||||
}
|
||||
|
||||
vec3 sCurve(vec3 x) {
|
||||
return (3*x - 2*x*x)*x;
|
||||
}
|
||||
|
||||
vec3 getLight(vec3 pos, vec3 normal) {
|
||||
pos += normal/2;
|
||||
pos -= vec3(0.5, 0.5, 0.5);
|
||||
ivec3 start = ivec3(floor(pos));
|
||||
vec3 diff = sCurve(pos - start);
|
||||
vec3 invDiff = 1 - diff;
|
||||
|
||||
vec3 state = vec3(0);
|
||||
for(int dx = 0; dx < 2; dx++) {
|
||||
for(int dy = 0; dy < 2; dy++) {
|
||||
for(int dz = 0; dz < 2; dz++) {
|
||||
ivec3 delta = ivec3(dx, dy, dz);
|
||||
vec3 light = sampleLight(start + delta);
|
||||
bvec3 isOne = bvec3(notEqual(delta, ivec3(0)));
|
||||
vec3 interpolation = mix(invDiff, diff, isOne);
|
||||
state += light*interpolation.x*interpolation.y*interpolation.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
const float[6] normalVariations = float[6](
|
||||
1.0, //vec3(0, 1, 0),
|
||||
@ -142,6 +209,7 @@ void main() {
|
||||
float fogDistance = calculateFogDistance(dist, textureData[blockType].fogDensity*densityAdjustment);
|
||||
float airFogDistance = calculateFogDistance(dist, fog.density*densityAdjustment);
|
||||
vec3 fogColor = unpackColor(textureData[blockType].fogColor);
|
||||
vec3 light = getLight(chunkPos + startPosition/16.0/voxelSize, normals[faceNormal]);
|
||||
vec4 textureColor = texture(texture_sampler, textureCoords)*vec4(light*normalVariation, 1);
|
||||
if(isBackFace == 0) {
|
||||
textureColor.rgb *= textureColor.a;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#version 450
|
||||
|
||||
in vec3 mvVertexPos;
|
||||
in vec3 chunkPos;
|
||||
in vec3 light; // TODO: This doesn't work here.
|
||||
flat in int blockType;
|
||||
flat in int faceNormal;
|
||||
@ -15,6 +16,8 @@ in vec3 direction;
|
||||
|
||||
uniform sampler2DArray texture_sampler;
|
||||
uniform sampler2DArray emissionSampler;
|
||||
uniform uint chunkDataIndex;
|
||||
uniform vec3 ambientLight;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
@ -43,6 +46,69 @@ layout(std430, binding = 4) buffer _voxelModels
|
||||
VoxelModel voxelModels[];
|
||||
};
|
||||
|
||||
struct ChunkData {
|
||||
uint lightMapPtrs[6*6*6];
|
||||
};
|
||||
|
||||
struct LightData {
|
||||
int values[8*8*8];
|
||||
};
|
||||
|
||||
layout(std430, binding = 7) buffer _chunkData
|
||||
{
|
||||
ChunkData chunkData[];
|
||||
};
|
||||
layout(std430, binding = 8) buffer _lightData
|
||||
{
|
||||
LightData lightData[];
|
||||
};
|
||||
|
||||
vec3 sampleLight(ivec3 pos) {
|
||||
pos += 8;
|
||||
ivec3 rough = pos/8;
|
||||
int roughIndex = (rough.x*6 + rough.y)*6 + rough.z;
|
||||
ivec3 fine = pos&7;
|
||||
int fineIndex = (fine.x*8 + fine.y)*8 + fine.z;
|
||||
int lightValue = lightData[chunkData[chunkDataIndex].lightMapPtrs[roughIndex]].values[fineIndex];
|
||||
vec3 sunLight = vec3(
|
||||
lightValue >> 25 & 31,
|
||||
lightValue >> 20 & 31,
|
||||
lightValue >> 15 & 31
|
||||
);
|
||||
vec3 blockLight = vec3(
|
||||
lightValue >> 10 & 31,
|
||||
lightValue >> 5 & 31,
|
||||
lightValue >> 0 & 31
|
||||
);
|
||||
return max(sunLight*ambientLight, blockLight)/32;
|
||||
}
|
||||
|
||||
vec3 sCurve(vec3 x) {
|
||||
return (3*x - 2*x*x)*x;
|
||||
}
|
||||
|
||||
vec3 getLight(vec3 pos, vec3 normal) {
|
||||
pos += normal/2;
|
||||
pos -= vec3(0.5, 0.5, 0.5);
|
||||
ivec3 start = ivec3(floor(pos));
|
||||
vec3 diff = sCurve(pos - start);
|
||||
vec3 invDiff = 1 - diff;
|
||||
|
||||
vec3 state = vec3(0);
|
||||
for(int dx = 0; dx < 2; dx++) {
|
||||
for(int dy = 0; dy < 2; dy++) {
|
||||
for(int dz = 0; dz < 2; dz++) {
|
||||
ivec3 delta = ivec3(dx, dy, dz);
|
||||
vec3 light = sampleLight(start + delta);
|
||||
bvec3 isOne = bvec3(notEqual(delta, ivec3(0)));
|
||||
vec3 interpolation = mix(invDiff, diff, isOne);
|
||||
state += light*interpolation.x*interpolation.y*interpolation.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
const float[6] normalVariations = float[6](
|
||||
1.0, //vec3(0, 1, 0),
|
||||
@ -229,6 +295,8 @@ void main() {
|
||||
float normalVariation = normalVariations[result.normal];
|
||||
float lod = getLod(result.voxelPosition, result.normal, direction, variance);
|
||||
ivec2 textureCoords = getTextureCoords(result.voxelPosition, result.textureDir);
|
||||
vec3 pos = chunkPos + vec3(result.voxelPosition)/16.0 + 1.0/32.0;
|
||||
vec3 light = getLight(pos, normals[result.normal]);
|
||||
fragColor = mipMapSample(texture_sampler, textureCoords, textureIndex, lod)*vec4(light*normalVariation, 1);
|
||||
|
||||
if(!passDitherTest(fragColor.a)) discard;
|
||||
|
143
src/chunk.zig
143
src/chunk.zig
@ -411,6 +411,7 @@ pub const meshing = struct {
|
||||
voxelSize: c_int,
|
||||
zNear: c_int,
|
||||
zFar: c_int,
|
||||
chunkDataIndex: c_int,
|
||||
};
|
||||
pub var uniforms: UniformStruct = undefined;
|
||||
pub var voxelUniforms: UniformStruct = undefined;
|
||||
@ -419,6 +420,8 @@ pub const meshing = struct {
|
||||
var vbo: c_uint = undefined;
|
||||
var faces: std.ArrayList(u32) = undefined;
|
||||
pub var faceBuffer: graphics.LargeBuffer(FaceData) = undefined;
|
||||
pub var chunkBuffer: graphics.LargeBuffer(ChunkData) = undefined;
|
||||
pub var lightBuffer: graphics.LargeBuffer(LightData) = undefined;
|
||||
pub var quadsDrawn: usize = 0;
|
||||
pub var transparentQuadsDrawn: usize = 0;
|
||||
|
||||
@ -442,6 +445,11 @@ pub const meshing = struct {
|
||||
|
||||
faces = try std.ArrayList(u32).initCapacity(main.globalAllocator, 65536);
|
||||
try faceBuffer.init(main.globalAllocator, 1 << 20, 3);
|
||||
try chunkBuffer.init(main.globalAllocator, 1 << 10, 7);
|
||||
try lightBuffer.init(main.globalAllocator, 1 << 10, 8);
|
||||
var allocation: graphics.SubAllocation = .{.start = undefined, .len = 0};
|
||||
try lightBuffer.uploadData(&.{.{.values = .{0}**(8*8*8)}}, &allocation);
|
||||
std.debug.assert(allocation.start == 0); // Reserve 0 for null
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
@ -451,14 +459,20 @@ pub const meshing = struct {
|
||||
c.glDeleteBuffers(1, &vbo);
|
||||
faces.deinit();
|
||||
faceBuffer.deinit();
|
||||
chunkBuffer.deinit();
|
||||
lightBuffer.deinit();
|
||||
}
|
||||
|
||||
pub fn beginRender() !void {
|
||||
try faceBuffer.beginRender();
|
||||
try chunkBuffer.beginRender();
|
||||
try lightBuffer.beginRender();
|
||||
}
|
||||
|
||||
pub fn endRender() void {
|
||||
faceBuffer.endRender();
|
||||
chunkBuffer.endRender();
|
||||
lightBuffer.endRender();
|
||||
}
|
||||
|
||||
fn bindCommonUniforms(locations: *UniformStruct, projMatrix: Mat4f, ambient: Vec3f) void {
|
||||
@ -519,7 +533,15 @@ pub const meshing = struct {
|
||||
typ: u16,
|
||||
modelIndex: u16,
|
||||
},
|
||||
light: [4]u32 = .{0, 0, 0, 0},
|
||||
//light: [4]u32 = .{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
pub const ChunkData = extern struct {
|
||||
lightMapPtrs: [6*6*6]u32,
|
||||
};
|
||||
|
||||
pub const LightData = extern struct {
|
||||
values: [8*8*8]u32,
|
||||
};
|
||||
|
||||
const PrimitiveMesh = struct {
|
||||
@ -577,7 +599,20 @@ pub const meshing = struct {
|
||||
i += neighborFaces.items.len;
|
||||
}
|
||||
for(self.completeList) |*face| {
|
||||
face.light = getLight(parent, face.position.x, face.position.y, face.position.z, face.position.normal);
|
||||
if(face.blockAndModel.modelIndex != 0 or true) { // Non-cube model: Add all light data.
|
||||
for(&[_]i32{-1, 1}) |dx| {
|
||||
for(&[_]i32{-1, 1}) |dy| {
|
||||
for(&[_]i32{-1, 1}) |dz| {
|
||||
const x = @divFloor((face.position.x -% Neighbors.relX[face.position.normal] +% dx) +% 8, 8);
|
||||
const y = @divFloor((face.position.y -% Neighbors.relY[face.position.normal] +% dy) +% 8, 8);
|
||||
const z = @divFloor((face.position.z -% Neighbors.relZ[face.position.normal] +% dz) +% 8, 8);
|
||||
parent.needsLightData[@intCast((x*6 + y)*6 + z)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // TODO: Simpler/Faster approach for cube models.
|
||||
|
||||
}
|
||||
}
|
||||
try self.uploadData();
|
||||
}
|
||||
@ -754,6 +789,9 @@ pub const meshing = struct {
|
||||
lastTransparentUpdatePos: Vec3i = Vec3i{0, 0, 0},
|
||||
refCount: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(1),
|
||||
needsNeighborUpdate: bool = false,
|
||||
chunkData: ChunkData,
|
||||
chunkDataAllocation: graphics.SubAllocation = .{.start = 0, .len = 0},
|
||||
needsLightData: [6*6*6]bool = undefined,
|
||||
|
||||
chunkBorders: [6]BoundingRectToNeighborChunk = [1]BoundingRectToNeighborChunk{.{}} ** 6,
|
||||
|
||||
@ -770,10 +808,21 @@ pub const meshing = struct {
|
||||
.transparentMesh = .{},
|
||||
.chunk = chunk,
|
||||
.lightingData = lightingData,
|
||||
.chunkData = .{.lightMapPtrs = .{0}**(6*6*6)},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *ChunkMesh) void {
|
||||
chunkBuffer.free(self.chunkDataAllocation) catch |err| {
|
||||
std.log.err("Error while freeing mesh data: {s}", .{@errorName(err)});
|
||||
};
|
||||
for(self.chunkData.lightMapPtrs) |ptr| {
|
||||
if(ptr != 0) {
|
||||
lightBuffer.free(.{.start = @intCast(ptr), .len = 1}) catch |err| {
|
||||
std.log.err("Error while freeing mesh data: {s}", .{@errorName(err)});
|
||||
};
|
||||
}
|
||||
}
|
||||
std.debug.assert(self.refCount.load(.Monotonic) == 0);
|
||||
self.opaqueMesh.deinit();
|
||||
self.voxelMesh.deinit();
|
||||
@ -991,15 +1040,11 @@ pub const meshing = struct {
|
||||
}
|
||||
}
|
||||
if(neighborMesh != self) {
|
||||
try neighborMesh.opaqueMesh.finish(neighborMesh);
|
||||
try neighborMesh.voxelMesh.finish(neighborMesh);
|
||||
try neighborMesh.transparentMesh.finish(neighborMesh);
|
||||
try neighborMesh.finish();
|
||||
}
|
||||
}
|
||||
self.chunk.blocks[getIndex(x, y, z)] = newBlock;
|
||||
try self.opaqueMesh.finish(self);
|
||||
try self.voxelMesh.finish(self);
|
||||
try self.transparentMesh.finish(self);
|
||||
try self.finish();
|
||||
}
|
||||
|
||||
pub inline fn constructFaceData(block: Block, normal: u3, x: i32, y: i32, z: i32, comptime backFace: bool) FaceData {
|
||||
@ -1010,6 +1055,77 @@ pub const meshing = struct {
|
||||
};
|
||||
}
|
||||
|
||||
fn getValues(mesh: *ChunkMesh, wx: i32, wy: i32, wz: i32) [6]u8 {
|
||||
const x = (wx >> mesh.chunk.voxelSizeShift) & chunkMask;
|
||||
const y = (wy >> mesh.chunk.voxelSizeShift) & chunkMask;
|
||||
const z = (wz >> mesh.chunk.voxelSizeShift) & chunkMask;
|
||||
const index = getIndex(x, y, z);
|
||||
return .{
|
||||
mesh.lightingData.*[0].data[index],
|
||||
mesh.lightingData.*[1].data[index],
|
||||
mesh.lightingData.*[2].data[index],
|
||||
mesh.lightingData.*[3].data[index],
|
||||
mesh.lightingData.*[4].data[index],
|
||||
mesh.lightingData.*[5].data[index],
|
||||
};
|
||||
}
|
||||
|
||||
fn getLightAt(self: *ChunkMesh, x: i32, y: i32, z: i32) [6]u8 {
|
||||
const wx = self.pos.wx +% x*self.pos.voxelSize;
|
||||
const wy = self.pos.wy +% y*self.pos.voxelSize;
|
||||
const wz = self.pos.wz +% z*self.pos.voxelSize;
|
||||
if(x == x & chunkMask and y == y & chunkMask and z == z & chunkMask) {
|
||||
return self.getValues(wx, wy, wz);
|
||||
}
|
||||
const neighborMesh = renderer.RenderStructure.getMeshFromAnyLodFromRenderThread(wx, wy, wz, self.pos.voxelSize) orelse return .{0, 0, 0, 0, 0, 0};
|
||||
// TODO: If the neighbor mesh has a higher lod the transition isn't seamless.
|
||||
return neighborMesh.getValues(wx, wy, wz);
|
||||
}
|
||||
|
||||
fn getCompressedLightAt(self: *ChunkMesh, x: i32, y: i32, z: i32) u32 {
|
||||
const light = self.getLightAt(x, y, z);
|
||||
return (
|
||||
@as(u32, light[0]) << 25 |
|
||||
@as(u32, light[1]) << 20 |
|
||||
@as(u32, light[2]) << 15 |
|
||||
@as(u32, light[3]) << 10 |
|
||||
@as(u32, light[4]) << 5 |
|
||||
@as(u32, light[5]) << 0
|
||||
);
|
||||
}
|
||||
|
||||
fn finish(self: *ChunkMesh) !void {
|
||||
@memset(&self.needsLightData, false);
|
||||
try self.opaqueMesh.finish(self);
|
||||
try self.voxelMesh.finish(self);
|
||||
try self.transparentMesh.finish(self);
|
||||
for(0..6) |x| {
|
||||
for(0..6) |y| {
|
||||
for(0..6) |z| {
|
||||
const index = (x*6 + y)*6 + z;
|
||||
if(!self.needsLightData[index]) continue;
|
||||
var map: LightData = undefined;
|
||||
for(0..8) |dx| {
|
||||
for(0..8) |dy| {
|
||||
for(0..8) |dz| {
|
||||
map.values[(dx*8 + dy)*8 + dz] = self.getCompressedLightAt(@as(i32, @intCast(x*8 + dx)) - 8, @as(i32, @intCast(y*8 + dy)) - 8, @as(i32, @intCast(z*8 + dz)) - 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var allocation: graphics.SubAllocation = .{.start = undefined, .len = 0};
|
||||
if(self.chunkData.lightMapPtrs[index] != 0) {
|
||||
allocation.start = @intCast(self.chunkData.lightMapPtrs[index]);
|
||||
allocation.len = 1;
|
||||
}
|
||||
try lightBuffer.uploadData(&.{map}, &allocation);
|
||||
self.chunkData.lightMapPtrs[index] = allocation.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
try chunkBuffer.uploadData(&.{self.chunkData}, &self.chunkDataAllocation);
|
||||
}
|
||||
|
||||
pub fn uploadDataAndFinishNeighbors(self: *ChunkMesh) !void {
|
||||
for(Neighbors.iterable) |neighbor| {
|
||||
const nullNeighborMesh = renderer.RenderStructure.getNeighborFromRenderThread(self.pos, self.pos.voxelSize, neighbor);
|
||||
@ -1080,9 +1196,7 @@ pub const meshing = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
try neighborMesh.opaqueMesh.finish(neighborMesh);
|
||||
try neighborMesh.voxelMesh.finish(neighborMesh);
|
||||
try neighborMesh.transparentMesh.finish(neighborMesh);
|
||||
try neighborMesh.finish();
|
||||
continue;
|
||||
}
|
||||
// lod border:
|
||||
@ -1149,9 +1263,7 @@ pub const meshing = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
try self.opaqueMesh.finish(self);
|
||||
try self.voxelMesh.finish(self);
|
||||
try self.transparentMesh.finish(self);
|
||||
try self.finish();
|
||||
}
|
||||
|
||||
pub fn render(self: *ChunkMesh, playerPosition: Vec3d) void {
|
||||
@ -1164,6 +1276,7 @@ pub const meshing = struct {
|
||||
);
|
||||
c.glUniform1i(uniforms.visibilityMask, self.visibilityMask);
|
||||
c.glUniform1i(uniforms.voxelSize, self.pos.voxelSize);
|
||||
c.glUniform1ui(uniforms.chunkDataIndex, self.chunkDataAllocation.start);
|
||||
quadsDrawn += self.opaqueMesh.vertexCount/6;
|
||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, self.opaqueMesh.vertexCount, c.GL_UNSIGNED_INT, null, self.opaqueMesh.bufferAllocation.start*4);
|
||||
}
|
||||
@ -1178,6 +1291,7 @@ pub const meshing = struct {
|
||||
);
|
||||
c.glUniform1i(voxelUniforms.visibilityMask, self.visibilityMask);
|
||||
c.glUniform1i(voxelUniforms.voxelSize, self.pos.voxelSize);
|
||||
c.glUniform1ui(voxelUniforms.chunkDataIndex, self.chunkDataAllocation.start);
|
||||
quadsDrawn += self.voxelMesh.vertexCount/6;
|
||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, self.voxelMesh.vertexCount, c.GL_UNSIGNED_INT, null, self.voxelMesh.bufferAllocation.start*4);
|
||||
}
|
||||
@ -1279,6 +1393,7 @@ pub const meshing = struct {
|
||||
);
|
||||
c.glUniform1i(transparentUniforms.visibilityMask, self.visibilityMask);
|
||||
c.glUniform1i(transparentUniforms.voxelSize, self.pos.voxelSize);
|
||||
c.glUniform1ui(transparentUniforms.chunkDataIndex, self.chunkDataAllocation.start);
|
||||
transparentQuadsDrawn += self.culledSortingCount;
|
||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, self.culledSortingCount*6, c.GL_UNSIGNED_INT, null, self.transparentMesh.bufferAllocation.start*4);
|
||||
}
|
||||
|
@ -1332,7 +1332,7 @@ pub fn LargeBuffer(comptime Entry: type) type {
|
||||
try self.fencedFreeLists[self.activeFence].append(allocation);
|
||||
}
|
||||
|
||||
pub fn uploadData(self: *Self, data: []Entry, allocation: *SubAllocation) !void {
|
||||
pub fn uploadData(self: *Self, data: []const Entry, allocation: *SubAllocation) !void {
|
||||
try self.free(allocation.*);
|
||||
if(data.len == 0) {
|
||||
allocation.len = 0;
|
||||
@ -1854,9 +1854,7 @@ pub fn generateBlockTexture(blockType: u16) !Texture {
|
||||
faceData[faces + 1] = main.chunk.meshing.ChunkMesh.constructFaceData(block, main.chunk.Neighbors.dirUp, 1, 1+1, 1, false);
|
||||
faceData[faces + 2] = main.chunk.meshing.ChunkMesh.constructFaceData(block, main.chunk.Neighbors.dirPosZ, 1, 1, 1+1, false);
|
||||
faces += 3;
|
||||
for(faceData[0..faces]) |*face| {
|
||||
@memset(&face.light, ~@as(u32, 0));
|
||||
}
|
||||
// TODO: Lighting
|
||||
var allocation: SubAllocation = .{.start = 0, .len = 0};
|
||||
try main.chunk.meshing.faceBuffer.uploadData(faceData[0..faces], &allocation);
|
||||
|
||||
|
@ -41,7 +41,13 @@ fn flawedRender() !void {
|
||||
try draw.print("Queue size: {}", .{main.threadPool.queueSize()}, 0, y, 8, .left);
|
||||
y += 8;
|
||||
const faceDataSize = @sizeOf(main.chunk.meshing.FaceData);
|
||||
try draw.print("ChunkMesh memory: {} MiB / {} MiB (fragmentation: {})", .{main.chunk.meshing.faceBuffer.used*faceDataSize >> 20, main.chunk.meshing.faceBuffer.capacity*faceDataSize >> 20, main.chunk.meshing.faceBuffer.freeBlocks.items.len}, 0, y, 8, .left);
|
||||
try draw.print("Chunk Face memory: {} MiB / {} MiB (fragmentation: {})", .{main.chunk.meshing.faceBuffer.used*faceDataSize >> 20, main.chunk.meshing.faceBuffer.capacity*faceDataSize >> 20, main.chunk.meshing.faceBuffer.freeBlocks.items.len}, 0, y, 8, .left);
|
||||
y += 8;
|
||||
const chunkDataSize = @sizeOf(main.chunk.meshing.ChunkData);
|
||||
try draw.print("Chunk memory: {} MiB / {} MiB (fragmentation: {})", .{main.chunk.meshing.chunkBuffer.used*chunkDataSize >> 20, main.chunk.meshing.chunkBuffer.capacity*chunkDataSize >> 20, main.chunk.meshing.chunkBuffer.freeBlocks.items.len}, 0, y, 8, .left);
|
||||
y += 8;
|
||||
const lightDataSize = @sizeOf(main.chunk.meshing.LightData);
|
||||
try draw.print("Chunk light memory: {} MiB / {} MiB (fragmentation: {})", .{main.chunk.meshing.lightBuffer.used*lightDataSize >> 20, main.chunk.meshing.lightBuffer.capacity*lightDataSize >> 20, main.chunk.meshing.lightBuffer.freeBlocks.items.len}, 0, y, 8, .left);
|
||||
y += 8;
|
||||
try draw.print("Biome: {s}", .{main.game.world.?.playerBiome.load(.Monotonic).id}, 0, y, 8, .left);
|
||||
y += 8;
|
||||
|
Loading…
x
Reference in New Issue
Block a user