mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -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 mvVertexPos;
|
||||||
in vec3 light;
|
in vec3 light;
|
||||||
|
in vec3 chunkPos;
|
||||||
flat in int blockType;
|
flat in int blockType;
|
||||||
flat in int faceNormal;
|
flat in int faceNormal;
|
||||||
flat in int modelIndex;
|
flat in int modelIndex;
|
||||||
@ -15,6 +16,9 @@ in vec3 direction;
|
|||||||
|
|
||||||
uniform sampler2DArray texture_sampler;
|
uniform sampler2DArray texture_sampler;
|
||||||
uniform sampler2DArray emissionSampler;
|
uniform sampler2DArray emissionSampler;
|
||||||
|
uniform uint chunkDataIndex;
|
||||||
|
uniform vec3 ambientLight;
|
||||||
|
uniform int voxelSize;
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
@ -31,6 +35,69 @@ layout(std430, binding = 1) buffer _textureData
|
|||||||
TextureData 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](
|
const float[6] normalVariations = float[6](
|
||||||
1.0, //vec3(0, 1, 0),
|
1.0, //vec3(0, 1, 0),
|
||||||
@ -40,6 +107,14 @@ const float[6] normalVariations = float[6](
|
|||||||
0.96, //vec3(0, 0, 1),
|
0.96, //vec3(0, 0, 1),
|
||||||
0.88 //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] (
|
float ditherThresholds[16] = float[16] (
|
||||||
1/17.0, 9/17.0, 3/17.0, 11/17.0,
|
1/17.0, 9/17.0, 3/17.0, 11/17.0,
|
||||||
@ -82,6 +157,7 @@ void main() {
|
|||||||
uint textureIndex = textureData[blockType].textureIndices[faceNormal];
|
uint textureIndex = textureData[blockType].textureIndices[faceNormal];
|
||||||
float normalVariation = normalVariations[faceNormal];
|
float normalVariation = normalVariations[faceNormal];
|
||||||
vec3 textureCoords = vec3(getTextureCoordsNormal(startPosition/16, faceNormal), textureIndex);
|
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);
|
fragColor = texture(texture_sampler, textureCoords)*vec4(light*normalVariation, 1);
|
||||||
|
|
||||||
if(!passDitherTest(fragColor.a)) discard;
|
if(!passDitherTest(fragColor.a)) discard;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
out vec3 mvVertexPos;
|
out vec3 mvVertexPos;
|
||||||
out vec3 light;
|
out vec3 light;
|
||||||
|
out vec3 chunkPos;
|
||||||
flat out int blockType;
|
flat out int blockType;
|
||||||
flat out int modelIndex;
|
flat out int modelIndex;
|
||||||
flat out int faceNormal;
|
flat out int faceNormal;
|
||||||
@ -22,7 +23,6 @@ uniform vec3 modelPosition;
|
|||||||
struct FaceData {
|
struct FaceData {
|
||||||
int encodedPositionAndNormalsAndPermutation;
|
int encodedPositionAndNormalsAndPermutation;
|
||||||
int blockAndModel;
|
int blockAndModel;
|
||||||
int light[4];
|
|
||||||
};
|
};
|
||||||
layout(std430, binding = 3) buffer _faceData
|
layout(std430, binding = 3) buffer _faceData
|
||||||
{
|
{
|
||||||
@ -131,18 +131,7 @@ void main() {
|
|||||||
int vertexID = gl_VertexID%4;
|
int vertexID = gl_VertexID%4;
|
||||||
int encodedPositionAndNormalsAndPermutation = faceData[faceID].encodedPositionAndNormalsAndPermutation;
|
int encodedPositionAndNormalsAndPermutation = faceData[faceID].encodedPositionAndNormalsAndPermutation;
|
||||||
int blockAndModel = faceData[faceID].blockAndModel;
|
int blockAndModel = faceData[faceID].blockAndModel;
|
||||||
int fullLight = faceData[faceID].light[vertexID];
|
light = vec3(1, 1, 1);
|
||||||
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;
|
|
||||||
isBackFace = encodedPositionAndNormalsAndPermutation>>19 & 1;
|
isBackFace = encodedPositionAndNormalsAndPermutation>>19 & 1;
|
||||||
int oldNormal = (encodedPositionAndNormalsAndPermutation >> 20) & 7;
|
int oldNormal = (encodedPositionAndNormalsAndPermutation >> 20) & 7;
|
||||||
mat3 permutationMatrix = permutationMatrices[(encodedPositionAndNormalsAndPermutation >> 23) & 7];
|
mat3 permutationMatrix = permutationMatrices[(encodedPositionAndNormalsAndPermutation >> 23) & 7];
|
||||||
@ -158,6 +147,7 @@ void main() {
|
|||||||
encodedPositionAndNormalsAndPermutation >> 5 & 31,
|
encodedPositionAndNormalsAndPermutation >> 5 & 31,
|
||||||
encodedPositionAndNormalsAndPermutation >> 10 & 31
|
encodedPositionAndNormalsAndPermutation >> 10 & 31
|
||||||
);
|
);
|
||||||
|
chunkPos = vec3(position) - normals[normal];
|
||||||
int octantIndex = (position.x >> 4) | (position.y >> 4)<<1 | (position.z >> 4)<<2;
|
int octantIndex = (position.x >> 4) | (position.y >> 4)<<1 | (position.z >> 4)<<2;
|
||||||
if((visibilityMask & 1<<octantIndex) == 0) { // discard face
|
if((visibilityMask & 1<<octantIndex) == 0) { // discard face
|
||||||
gl_Position = vec4(-2, -2, -2, 1);
|
gl_Position = vec4(-2, -2, -2, 1);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
in vec3 mvVertexPos;
|
in vec3 mvVertexPos;
|
||||||
in vec3 light;
|
in vec3 light;
|
||||||
|
in vec3 chunkPos;
|
||||||
flat in int blockType;
|
flat in int blockType;
|
||||||
flat in int faceNormal;
|
flat in int faceNormal;
|
||||||
flat in int modelIndex;
|
flat in int modelIndex;
|
||||||
@ -16,6 +17,9 @@ uniform sampler2DArray texture_sampler;
|
|||||||
uniform sampler2DArray emissionSampler;
|
uniform sampler2DArray emissionSampler;
|
||||||
uniform samplerCube reflectionMap;
|
uniform samplerCube reflectionMap;
|
||||||
uniform float reflectionMapSize;
|
uniform float reflectionMapSize;
|
||||||
|
uniform uint chunkDataIndex;
|
||||||
|
uniform vec3 ambientLight;
|
||||||
|
uniform int voxelSize;
|
||||||
|
|
||||||
layout(binding = 3) uniform sampler2D depthTexture;
|
layout(binding = 3) uniform sampler2D depthTexture;
|
||||||
|
|
||||||
@ -40,6 +44,69 @@ layout(std430, binding = 1) buffer _textureData
|
|||||||
TextureData 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](
|
const float[6] normalVariations = float[6](
|
||||||
1.0, //vec3(0, 1, 0),
|
1.0, //vec3(0, 1, 0),
|
||||||
@ -142,6 +209,7 @@ void main() {
|
|||||||
float fogDistance = calculateFogDistance(dist, textureData[blockType].fogDensity*densityAdjustment);
|
float fogDistance = calculateFogDistance(dist, textureData[blockType].fogDensity*densityAdjustment);
|
||||||
float airFogDistance = calculateFogDistance(dist, fog.density*densityAdjustment);
|
float airFogDistance = calculateFogDistance(dist, fog.density*densityAdjustment);
|
||||||
vec3 fogColor = unpackColor(textureData[blockType].fogColor);
|
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);
|
vec4 textureColor = texture(texture_sampler, textureCoords)*vec4(light*normalVariation, 1);
|
||||||
if(isBackFace == 0) {
|
if(isBackFace == 0) {
|
||||||
textureColor.rgb *= textureColor.a;
|
textureColor.rgb *= textureColor.a;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
in vec3 mvVertexPos;
|
in vec3 mvVertexPos;
|
||||||
|
in vec3 chunkPos;
|
||||||
in vec3 light; // TODO: This doesn't work here.
|
in vec3 light; // TODO: This doesn't work here.
|
||||||
flat in int blockType;
|
flat in int blockType;
|
||||||
flat in int faceNormal;
|
flat in int faceNormal;
|
||||||
@ -15,6 +16,8 @@ in vec3 direction;
|
|||||||
|
|
||||||
uniform sampler2DArray texture_sampler;
|
uniform sampler2DArray texture_sampler;
|
||||||
uniform sampler2DArray emissionSampler;
|
uniform sampler2DArray emissionSampler;
|
||||||
|
uniform uint chunkDataIndex;
|
||||||
|
uniform vec3 ambientLight;
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
@ -43,6 +46,69 @@ layout(std430, binding = 4) buffer _voxelModels
|
|||||||
VoxelModel 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](
|
const float[6] normalVariations = float[6](
|
||||||
1.0, //vec3(0, 1, 0),
|
1.0, //vec3(0, 1, 0),
|
||||||
@ -229,6 +295,8 @@ void main() {
|
|||||||
float normalVariation = normalVariations[result.normal];
|
float normalVariation = normalVariations[result.normal];
|
||||||
float lod = getLod(result.voxelPosition, result.normal, direction, variance);
|
float lod = getLod(result.voxelPosition, result.normal, direction, variance);
|
||||||
ivec2 textureCoords = getTextureCoords(result.voxelPosition, result.textureDir);
|
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);
|
fragColor = mipMapSample(texture_sampler, textureCoords, textureIndex, lod)*vec4(light*normalVariation, 1);
|
||||||
|
|
||||||
if(!passDitherTest(fragColor.a)) discard;
|
if(!passDitherTest(fragColor.a)) discard;
|
||||||
|
143
src/chunk.zig
143
src/chunk.zig
@ -411,6 +411,7 @@ pub const meshing = struct {
|
|||||||
voxelSize: c_int,
|
voxelSize: c_int,
|
||||||
zNear: c_int,
|
zNear: c_int,
|
||||||
zFar: c_int,
|
zFar: c_int,
|
||||||
|
chunkDataIndex: c_int,
|
||||||
};
|
};
|
||||||
pub var uniforms: UniformStruct = undefined;
|
pub var uniforms: UniformStruct = undefined;
|
||||||
pub var voxelUniforms: UniformStruct = undefined;
|
pub var voxelUniforms: UniformStruct = undefined;
|
||||||
@ -419,6 +420,8 @@ pub const meshing = struct {
|
|||||||
var vbo: c_uint = undefined;
|
var vbo: c_uint = undefined;
|
||||||
var faces: std.ArrayList(u32) = undefined;
|
var faces: std.ArrayList(u32) = undefined;
|
||||||
pub var faceBuffer: graphics.LargeBuffer(FaceData) = 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 quadsDrawn: usize = 0;
|
||||||
pub var transparentQuadsDrawn: usize = 0;
|
pub var transparentQuadsDrawn: usize = 0;
|
||||||
|
|
||||||
@ -442,6 +445,11 @@ pub const meshing = struct {
|
|||||||
|
|
||||||
faces = try std.ArrayList(u32).initCapacity(main.globalAllocator, 65536);
|
faces = try std.ArrayList(u32).initCapacity(main.globalAllocator, 65536);
|
||||||
try faceBuffer.init(main.globalAllocator, 1 << 20, 3);
|
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 {
|
pub fn deinit() void {
|
||||||
@ -451,14 +459,20 @@ pub const meshing = struct {
|
|||||||
c.glDeleteBuffers(1, &vbo);
|
c.glDeleteBuffers(1, &vbo);
|
||||||
faces.deinit();
|
faces.deinit();
|
||||||
faceBuffer.deinit();
|
faceBuffer.deinit();
|
||||||
|
chunkBuffer.deinit();
|
||||||
|
lightBuffer.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn beginRender() !void {
|
pub fn beginRender() !void {
|
||||||
try faceBuffer.beginRender();
|
try faceBuffer.beginRender();
|
||||||
|
try chunkBuffer.beginRender();
|
||||||
|
try lightBuffer.beginRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endRender() void {
|
pub fn endRender() void {
|
||||||
faceBuffer.endRender();
|
faceBuffer.endRender();
|
||||||
|
chunkBuffer.endRender();
|
||||||
|
lightBuffer.endRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bindCommonUniforms(locations: *UniformStruct, projMatrix: Mat4f, ambient: Vec3f) void {
|
fn bindCommonUniforms(locations: *UniformStruct, projMatrix: Mat4f, ambient: Vec3f) void {
|
||||||
@ -519,7 +533,15 @@ pub const meshing = struct {
|
|||||||
typ: u16,
|
typ: u16,
|
||||||
modelIndex: 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 {
|
const PrimitiveMesh = struct {
|
||||||
@ -577,7 +599,20 @@ pub const meshing = struct {
|
|||||||
i += neighborFaces.items.len;
|
i += neighborFaces.items.len;
|
||||||
}
|
}
|
||||||
for(self.completeList) |*face| {
|
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();
|
try self.uploadData();
|
||||||
}
|
}
|
||||||
@ -754,6 +789,9 @@ pub const meshing = struct {
|
|||||||
lastTransparentUpdatePos: Vec3i = Vec3i{0, 0, 0},
|
lastTransparentUpdatePos: Vec3i = Vec3i{0, 0, 0},
|
||||||
refCount: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(1),
|
refCount: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(1),
|
||||||
needsNeighborUpdate: bool = false,
|
needsNeighborUpdate: bool = false,
|
||||||
|
chunkData: ChunkData,
|
||||||
|
chunkDataAllocation: graphics.SubAllocation = .{.start = 0, .len = 0},
|
||||||
|
needsLightData: [6*6*6]bool = undefined,
|
||||||
|
|
||||||
chunkBorders: [6]BoundingRectToNeighborChunk = [1]BoundingRectToNeighborChunk{.{}} ** 6,
|
chunkBorders: [6]BoundingRectToNeighborChunk = [1]BoundingRectToNeighborChunk{.{}} ** 6,
|
||||||
|
|
||||||
@ -770,10 +808,21 @@ pub const meshing = struct {
|
|||||||
.transparentMesh = .{},
|
.transparentMesh = .{},
|
||||||
.chunk = chunk,
|
.chunk = chunk,
|
||||||
.lightingData = lightingData,
|
.lightingData = lightingData,
|
||||||
|
.chunkData = .{.lightMapPtrs = .{0}**(6*6*6)},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *ChunkMesh) void {
|
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);
|
std.debug.assert(self.refCount.load(.Monotonic) == 0);
|
||||||
self.opaqueMesh.deinit();
|
self.opaqueMesh.deinit();
|
||||||
self.voxelMesh.deinit();
|
self.voxelMesh.deinit();
|
||||||
@ -991,15 +1040,11 @@ pub const meshing = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(neighborMesh != self) {
|
if(neighborMesh != self) {
|
||||||
try neighborMesh.opaqueMesh.finish(neighborMesh);
|
try neighborMesh.finish();
|
||||||
try neighborMesh.voxelMesh.finish(neighborMesh);
|
|
||||||
try neighborMesh.transparentMesh.finish(neighborMesh);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.chunk.blocks[getIndex(x, y, z)] = newBlock;
|
self.chunk.blocks[getIndex(x, y, z)] = newBlock;
|
||||||
try self.opaqueMesh.finish(self);
|
try self.finish();
|
||||||
try self.voxelMesh.finish(self);
|
|
||||||
try self.transparentMesh.finish(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn constructFaceData(block: Block, normal: u3, x: i32, y: i32, z: i32, comptime backFace: bool) FaceData {
|
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 {
|
pub fn uploadDataAndFinishNeighbors(self: *ChunkMesh) !void {
|
||||||
for(Neighbors.iterable) |neighbor| {
|
for(Neighbors.iterable) |neighbor| {
|
||||||
const nullNeighborMesh = renderer.RenderStructure.getNeighborFromRenderThread(self.pos, self.pos.voxelSize, 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.finish();
|
||||||
try neighborMesh.voxelMesh.finish(neighborMesh);
|
|
||||||
try neighborMesh.transparentMesh.finish(neighborMesh);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// lod border:
|
// lod border:
|
||||||
@ -1149,9 +1263,7 @@ pub const meshing = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try self.opaqueMesh.finish(self);
|
try self.finish();
|
||||||
try self.voxelMesh.finish(self);
|
|
||||||
try self.transparentMesh.finish(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *ChunkMesh, playerPosition: Vec3d) void {
|
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.visibilityMask, self.visibilityMask);
|
||||||
c.glUniform1i(uniforms.voxelSize, self.pos.voxelSize);
|
c.glUniform1i(uniforms.voxelSize, self.pos.voxelSize);
|
||||||
|
c.glUniform1ui(uniforms.chunkDataIndex, self.chunkDataAllocation.start);
|
||||||
quadsDrawn += self.opaqueMesh.vertexCount/6;
|
quadsDrawn += self.opaqueMesh.vertexCount/6;
|
||||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, self.opaqueMesh.vertexCount, c.GL_UNSIGNED_INT, null, self.opaqueMesh.bufferAllocation.start*4);
|
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.visibilityMask, self.visibilityMask);
|
||||||
c.glUniform1i(voxelUniforms.voxelSize, self.pos.voxelSize);
|
c.glUniform1i(voxelUniforms.voxelSize, self.pos.voxelSize);
|
||||||
|
c.glUniform1ui(voxelUniforms.chunkDataIndex, self.chunkDataAllocation.start);
|
||||||
quadsDrawn += self.voxelMesh.vertexCount/6;
|
quadsDrawn += self.voxelMesh.vertexCount/6;
|
||||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, self.voxelMesh.vertexCount, c.GL_UNSIGNED_INT, null, self.voxelMesh.bufferAllocation.start*4);
|
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.visibilityMask, self.visibilityMask);
|
||||||
c.glUniform1i(transparentUniforms.voxelSize, self.pos.voxelSize);
|
c.glUniform1i(transparentUniforms.voxelSize, self.pos.voxelSize);
|
||||||
|
c.glUniform1ui(transparentUniforms.chunkDataIndex, self.chunkDataAllocation.start);
|
||||||
transparentQuadsDrawn += self.culledSortingCount;
|
transparentQuadsDrawn += self.culledSortingCount;
|
||||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, self.culledSortingCount*6, c.GL_UNSIGNED_INT, null, self.transparentMesh.bufferAllocation.start*4);
|
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);
|
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.*);
|
try self.free(allocation.*);
|
||||||
if(data.len == 0) {
|
if(data.len == 0) {
|
||||||
allocation.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 + 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);
|
faceData[faces + 2] = main.chunk.meshing.ChunkMesh.constructFaceData(block, main.chunk.Neighbors.dirPosZ, 1, 1, 1+1, false);
|
||||||
faces += 3;
|
faces += 3;
|
||||||
for(faceData[0..faces]) |*face| {
|
// TODO: Lighting
|
||||||
@memset(&face.light, ~@as(u32, 0));
|
|
||||||
}
|
|
||||||
var allocation: SubAllocation = .{.start = 0, .len = 0};
|
var allocation: SubAllocation = .{.start = 0, .len = 0};
|
||||||
try main.chunk.meshing.faceBuffer.uploadData(faceData[0..faces], &allocation);
|
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);
|
try draw.print("Queue size: {}", .{main.threadPool.queueSize()}, 0, y, 8, .left);
|
||||||
y += 8;
|
y += 8;
|
||||||
const faceDataSize = @sizeOf(main.chunk.meshing.FaceData);
|
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;
|
y += 8;
|
||||||
try draw.print("Biome: {s}", .{main.game.world.?.playerBiome.load(.Monotonic).id}, 0, y, 8, .left);
|
try draw.print("Biome: {s}", .{main.game.world.?.playerBiome.load(.Monotonic).id}, 0, y, 8, .left);
|
||||||
y += 8;
|
y += 8;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user