Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6d77f95
first test
codemob-dev May 25, 2026
6322a5a
more progress?
codemob-dev May 26, 2026
2b28a0d
Make it look better
codemob-dev May 26, 2026
0245cbb
fix flickering
codemob-dev May 26, 2026
949eb7d
fix grass and angle sun
codemob-dev May 26, 2026
d76ee06
Pixel aligned shadows (but still bias!!!)
codemob-dev May 26, 2026
01193d3
painnnnn
codemob-dev May 26, 2026
c47ff41
even more pain
codemob-dev May 26, 2026
ac77d71
painiest pain
codemob-dev May 26, 2026
ea5b91c
Directional shading!!!!!
codemob-dev May 27, 2026
15292a5
tweaky the numbers
codemob-dev May 27, 2026
16aaf1b
lower resolution
codemob-dev May 27, 2026
4360d44
Fix a small bug
codemob-dev May 29, 2026
c1fce04
Merge branch 'master' into shadow-maps
codemob-dev May 29, 2026
aab9a84
Fix the visibility state issues
codemob-dev May 30, 2026
7cbc7af
Formatting
codemob-dev May 30, 2026
cab93f9
Mostly working version
codemob-dev May 31, 2026
e0d2da3
Debug line
codemob-dev May 31, 2026
ed23177
Revert "Debug line"
codemob-dev May 31, 2026
b625737
Revert "Mostly working version"
codemob-dev May 31, 2026
175d035
Make light sources remove shadows
codemob-dev May 31, 2026
7129cc3
bluer shadows
codemob-dev May 31, 2026
2cad062
Do the magic
IntegratedQuantum May 31, 2026
dbb5af1
tweaks (waow)!
codemob-dev May 31, 2026
7e2939c
Formatting
codemob-dev May 31, 2026
a8c2bae
Formatting++!
codemob-dev May 31, 2026
ab47db5
Merge branch 'master' into shadow-maps
codemob-dev May 31, 2026
b107904
Remove unused mat4f function
codemob-dev May 31, 2026
21ee80a
Fix compilation when merged with master
codemob-dev May 31, 2026
5fcb418
Merge branch 'master' into shadow-maps
codemob-dev Jul 16, 2026
4344f31
Fix compilation
codemob-dev Jul 16, 2026
038cb44
Grr stupid formatting
codemob-dev Jul 16, 2026
26c7211
Properly implement frustum culling and fix the culling problems (yay!)
codemob-dev Jul 17, 2026
5ed30f0
Merge branch 'master' into shadow-maps
codemob-dev Jul 17, 2026
30b78f9
Add visibilityStateDepth to chunk_data.glsl
codemob-dev Jul 17, 2026
c934147
Add back isDepth
codemob-dev Jul 17, 2026
19c974f
Redo the pixel perfect system
codemob-dev Jul 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions assets/cubyz/shaders/chunks/chunk_depth_fragment.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#version 460

layout(location = 1) in vec3 direction;
layout(location = 2) in vec2 uv;
layout(location = 3) flat in vec3 normal;
layout(location = 4) flat in int textureIndex;
layout(location = 5) flat in int isBackFace;
layout(location = 7) flat in int opaqueInLod;

layout(location = 5) uniform float lodDistance;

layout(binding = 0) uniform sampler2DArray textureSampler;
layout(binding = 5) uniform sampler2D ditherTexture;

layout(std430, binding = 1) buffer _animatedTexture
{
float animatedTexture[];
};

void main() {
float animatedTextureIndex = animatedTexture[textureIndex];
vec3 textureCoords = vec3(uv, animatedTextureIndex);
vec4 color = texture(textureSampler, textureCoords);
if (color.a < 0.5) discard;
}
97 changes: 97 additions & 0 deletions assets/cubyz/shaders/chunks/chunk_depth_vertex.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#version 460

layout(location = 1) out vec3 direction;
layout(location = 2) out vec2 uv;
layout(location = 3) flat out vec3 normal;
layout(location = 4) flat out int textureIndex;
layout(location = 5) flat out int isBackFace;
layout(location = 7) flat out int opaqueInLod;

layout(location = 1) uniform mat4 projectionMatrix;
layout(location = 2) uniform mat4 viewMatrix;
layout(location = 3) uniform ivec3 playerPositionInteger;
layout(location = 4) uniform vec3 playerPositionFraction;

struct FaceData {
int encodedPositionAndLightIndex;
int textureAndQuad;
};
layout(std430, binding = 3) buffer _faceData
{
FaceData faceData[];
};

struct QuadInfo {
vec3 normal;
float corners[4][3];
vec2 cornerUV[4];
uint textureSlot;
int opaqueInLod;
};

layout(std430, binding = 4) buffer _quads
{
QuadInfo quads[];
};

layout(std430, binding = 10) buffer _lightData
{
uint lightData[];
};

struct ChunkData {
ivec4 position;
vec4 minPos;
vec4 maxPos;
int voxelSize;
uint lightStart;
uint vertexStartOpaque;
uint faceCountsByNormalOpaque[14];
uint vertexStartTransparent;
uint vertexCountTransparent;
uint visibilityState;
uint oldVisibilityState;
uint visibilityStateDepth;
uint oldVisibilityStateDepth;
};

layout(std430, binding = 6) buffer _chunks
{
ChunkData chunks[];
};

vec3 square(vec3 x) {
return x*x;
}

void main() {
int faceID = gl_VertexID >> 2;
int vertexID = gl_VertexID & 3;
int chunkID = gl_BaseInstance;
int voxelSize = chunks[chunkID].voxelSize;
int encodedPositionAndLightIndex = faceData[faceID].encodedPositionAndLightIndex;
int textureAndQuad = faceData[faceID].textureAndQuad;
isBackFace = encodedPositionAndLightIndex>>15 & 1;

textureIndex = textureAndQuad & 65535;
int quadIndex = textureAndQuad >> 16;

vec3 position = vec3(
encodedPositionAndLightIndex & 31,
encodedPositionAndLightIndex >> 5 & 31,
encodedPositionAndLightIndex >> 10 & 31
);

normal = quads[quadIndex].normal;

position += vec3(quads[quadIndex].corners[vertexID][0], quads[quadIndex].corners[vertexID][1], quads[quadIndex].corners[vertexID][2]);
position *= voxelSize;
position += vec3(chunks[chunkID].position.xyz - playerPositionInteger);
position -= playerPositionFraction;

direction = position;

gl_Position = projectionMatrix*viewMatrix*vec4(position, 1);
uv = quads[quadIndex].cornerUV[vertexID]*voxelSize;
opaqueInLod = quads[quadIndex].opaqueInLod;
}
51 changes: 44 additions & 7 deletions assets/cubyz/shaders/chunks/chunk_fragment.frag
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

layout(location = 0) in vec3 mvVertexPos;
layout(location = 1) in vec3 direction;
layout(location = 2) in vec3 light;
layout(location = 3) in vec2 uv;
layout(location = 4) flat in vec3 normal;
layout(location = 5) flat in int textureIndex;
layout(location = 6) flat in int isBackFace;
layout(location = 7) flat in float distanceForLodCheck;
layout(location = 8) flat in int opaqueInLod;
layout(location = 2) in vec3 sunLight;
layout(location = 3) in vec3 blockLight;
layout(location = 4) in vec2 uv;
layout(location = 5) in vec3 shadowPos;
layout(location = 6) flat in vec3 normal;
layout(location = 7) flat in int textureIndex;
layout(location = 8) flat in int isBackFace;
layout(location = 9) flat in float distanceForLodCheck;
layout(location = 10) flat in int opaqueInLod;
layout(location = 11) flat in mat4 worldToQuad;
layout(location = 15) flat in mat3 uvTransform;

layout(location = 0) out vec4 fragColor;

Expand All @@ -17,16 +21,24 @@ layout(binding = 1) uniform sampler2DArray emissionSampler;
layout(binding = 2) uniform sampler2DArray reflectivityAndAbsorptionSampler;
layout(binding = 4) uniform samplerCube reflectionMap;
layout(binding = 5) uniform sampler2D ditherTexture;
layout(binding = 6) uniform sampler2D shadowMap;

layout(location = 5) uniform float reflectionMapSize;
layout(location = 6) uniform float contrast;
layout(location = 7) uniform float lodDistance;
layout(location = 8) uniform mat4 lightProjectionMatrix;
layout(location = 9) uniform mat4 lightViewMatrix;
layout(location = 42) uniform vec3 lightDir;

layout(std430, binding = 1) buffer _animatedTexture
{
float animatedTexture[];
};

vec3 square(vec3 x) {
return x*x;
}

float lightVariation(vec3 normal) {
const vec3 directionalPart = vec3(0, contrast/2, contrast);
const float baseLighting = 1 - contrast;
Expand All @@ -51,6 +63,26 @@ vec4 fixedCubeMapLookup(vec3 v) { // Taken from http://the-witness.net/news/2012
return texture(reflectionMap, v);
}

float shadowCalculation() {
if (dot(lightDir, normal) > 0.0) return 1.0;

vec3 shadowPosUV = uvTransform * (worldToQuad * lightViewMatrix * vec4(shadowPos, 1.0)).xyz;
shadowPosUV.xy = ceil(shadowPosUV.xy * 16.0) / 16.0;
vec4 shadowPosSnapped = inverse(worldToQuad) * vec4(inverse(uvTransform) * shadowPosUV, 1.0);

vec4 lightPos = lightProjectionMatrix * shadowPosSnapped;
vec3 projCoords = lightPos.xyz;
projCoords = projCoords * 0.5 + 0.5;
float closestDepth = texture(shadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
currentDepth += 0.0001;
float shadow = currentDepth > closestDepth ? 1.0 : 0.0;
if(projCoords.z > 1.0) {
shadow = 0.0;
}
return shadow;
}

void main() {
float animatedTextureIndex = animatedTexture[textureIndex];
float normalVariation = lightVariation(normal);
Expand All @@ -63,6 +95,11 @@ void main() {
reflectivity = reflectivity*fixedCubeMapLookup(reflect(direction, normal)).x;
reflectivity = reflectivity*(1 - fresnelReflection) + fresnelReflection;

vec3 shadowColor = vec3(0.5, 0.5, 0.35);

float shadow = shadowCalculation();
vec3 light = min(sqrt(square((1.0 - shadow*shadowColor)*sunLight) + square(blockLight)), vec3(31))/31;

vec3 pixelLight = max(light*normalVariation, texture(emissionSampler, textureCoords).r*4);
fragColor = texture(textureSampler, textureCoords)*vec4(pixelLight, 1);
fragColor.rgb += reflectivity*pixelLight;
Expand Down
57 changes: 46 additions & 11 deletions assets/cubyz/shaders/chunks/chunk_vertex.vert
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

layout(location = 0) out vec3 mvVertexPos;
layout(location = 1) out vec3 direction;
layout(location = 2) out vec3 light;
layout(location = 3) out vec2 uv;
layout(location = 4) flat out vec3 normal;
layout(location = 5) flat out int textureIndex;
layout(location = 6) flat out int isBackFace;
layout(location = 7) flat out float distanceForLodCheck;
layout(location = 8) flat out int opaqueInLod;
layout(location = 2) out vec3 sunLight;
layout(location = 3) out vec3 blockLight;
layout(location = 4) out vec2 uv;
layout(location = 5) out vec3 shadowPos;
layout(location = 6) flat out vec3 normal;
layout(location = 7) flat out int textureIndex;
layout(location = 8) flat out int isBackFace;
layout(location = 9) flat out float distanceForLodCheck;
layout(location = 10) flat out int opaqueInLod;
layout(location = 11) flat out mat4 worldToQuad;
layout(location = 15) flat out mat3 uvTransform;

layout(location = 0) uniform vec3 ambientLight;
layout(location = 1) uniform mat4 projectionMatrix;
layout(location = 2) uniform mat4 viewMatrix;
layout(location = 3) uniform ivec3 playerPositionInteger;
layout(location = 4) uniform vec3 playerPositionFraction;
layout(location = 8) uniform mat4 lightProjectionMatrix;
layout(location = 9) uniform mat4 lightViewMatrix;

#ifdef ENTITY
layout(location = 14) uniform mat4 modelMatrix;
Expand Down Expand Up @@ -62,17 +68,16 @@ void main() {
int textureAndQuad = faceData[faceID].textureAndQuad;
uint lightIndex = chunks[chunkID].lightStart + 4*(encodedPositionAndLightIndex >> 16);
uint fullLight = lightData[lightIndex + vertexID];
vec3 sunLight = vec3(
sunLight = vec3(
fullLight >> 25 & 31u,
fullLight >> 20 & 31u,
fullLight >> 15 & 31u
);
vec3 blockLight = vec3(
) * ambientLight;
blockLight = vec3(
fullLight >> 10 & 31u,
fullLight >> 5 & 31u,
fullLight >> 0 & 31u
);
light = min(sqrt(square(sunLight*ambientLight) + square(blockLight)), vec3(31))/31;
isBackFace = encodedPositionAndLightIndex>>15 & 1;

textureIndex = textureAndQuad & 65535;
Expand Down Expand Up @@ -103,4 +108,34 @@ void main() {
distanceForLodCheck = length(mvPos.xyz) + voxelSize;
uv = quads[quadIndex].cornerUV[vertexID]*voxelSize;
opaqueInLod = quads[quadIndex].opaqueInLod;

shadowPos = position + normal * 0.03;

vec3 p0 = vec3(quads[quadIndex].corners[0][0], quads[quadIndex].corners[0][1], quads[quadIndex].corners[0][2]);
vec3 p1 = vec3(quads[quadIndex].corners[1][0], quads[quadIndex].corners[1][1], quads[quadIndex].corners[1][2]);
vec3 p3 = vec3(quads[quadIndex].corners[3][0], quads[quadIndex].corners[3][1], quads[quadIndex].corners[3][2]);

vec2 uv0 = vec2(quads[quadIndex].cornerUV[0][0], quads[quadIndex].cornerUV[0][1]);
vec2 uv1 = vec2(quads[quadIndex].cornerUV[1][0], quads[quadIndex].cornerUV[1][1]);
vec2 uv3 = vec2(quads[quadIndex].cornerUV[3][0], quads[quadIndex].cornerUV[3][1]);

vec3 u = p1 - p0;
vec3 v = p3 - p0;
mat3 invBasis = inverse(mat3(u, v, cross(u,v)));

vec2 du = uv1 - uv0;
vec2 dv = uv3 - uv0;

uvTransform = mat3(
vec3(du, 0.0),
vec3(dv, 0.0),
vec3(uv0, 1.0)
);

worldToQuad = mat4(
vec4(invBasis[0], 0),
vec4(invBasis[1], 0),
vec4(invBasis[2], 0),
vec4(-(invBasis * p0),1)
);
}
36 changes: 31 additions & 5 deletions assets/cubyz/shaders/chunks/fillIndirectBuffer.comp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ layout(location = 5) uniform ivec3 playerPositionInteger;

layout(location = 6) uniform float lodDistance;

layout(location = 7) uniform bool isDepth;

bool isVisible(int dir, ivec3 playerDist) {
switch(dir) {
case 0: // dirUp
Expand Down Expand Up @@ -72,14 +74,31 @@ void main() {
uint commandIndexEnd = commandIndex + 8;
uint groupFaceOffset = 0;
uint groupFaceCount = 0;
uint oldoldvisibilityState = chunks[chunkID].oldVisibilityState;
uint oldoldvisibilityState;
if(isDepth) {
oldoldvisibilityState = chunks[chunkID].oldVisibilityStateDepth;
} else {
oldoldvisibilityState = chunks[chunkID].oldVisibilityState;
}
ivec3 playerDist = playerPositionInteger - chunks[chunkID].position.xyz;
if(playerDist.x > 0) playerDist.x = max(0, playerDist.x - 32*chunks[chunkID].voxelSize);
if(playerDist.y > 0) playerDist.y = max(0, playerDist.y - 32*chunks[chunkID].voxelSize);
if(playerDist.z > 0) playerDist.z = max(0, playerDist.z - 32*chunks[chunkID].voxelSize);
float playerDistSquare = dot(playerDist, playerDist);

if((onlyDrawPreviouslyInvisible && chunks[chunkID].oldVisibilityState == 0 && chunks[chunkID].visibilityState != 0) || (chunks[chunkID].oldVisibilityState != 0 && !onlyDrawPreviouslyInvisible)) {
uint oldVisibilityState;
if(isDepth) {
oldVisibilityState = chunks[chunkID].oldVisibilityStateDepth;
} else {
oldVisibilityState = chunks[chunkID].oldVisibilityState;
}
uint visibilityState;
if(isDepth) {
visibilityState = chunks[chunkID].visibilityStateDepth;
} else {
visibilityState = chunks[chunkID].visibilityState;
}
if((onlyDrawPreviouslyInvisible && oldVisibilityState == 0 && visibilityState != 0) || (oldVisibilityState != 0 && !onlyDrawPreviouslyInvisible)) {
for(int i = 0; i < 14; i++) {
if(playerDistSquare >= lodDistance*lodDistance && i == 7) break;
uint faceCount = chunks[chunkID].faceCountsByNormalOpaque[i];
Expand All @@ -97,16 +116,23 @@ void main() {
}
}
if(onlyDrawPreviouslyInvisible) {
chunks[chunkID].oldVisibilityState = chunks[chunkID].visibilityState;
chunks[chunkID].visibilityState = 0;
if(isDepth) {
chunks[chunkID].oldVisibilityStateDepth = chunks[chunkID].visibilityStateDepth;
chunks[chunkID].visibilityStateDepth = 0;
oldVisibilityState = chunks[chunkID].oldVisibilityStateDepth;
} else {
chunks[chunkID].oldVisibilityState = chunks[chunkID].visibilityState;
chunks[chunkID].visibilityState = 0;
oldVisibilityState = chunks[chunkID].oldVisibilityState;
}
}
if(groupFaceCount != 0) {
commands[commandIndex] = addCommand(6*groupFaceCount, chunks[chunkID].vertexStartOpaque + 4*groupFaceOffset, chunkID);
commandIndex += 1;
}

for(; commandIndex < commandIndexEnd; commandIndex++) {
commands[commandIndex] = DrawElementsIndirectCommand(0, 0, 0, 0, oldoldvisibilityState << 1 | chunks[chunkID].oldVisibilityState);
commands[commandIndex] = DrawElementsIndirectCommand(0, 0, 0, 0, oldoldvisibilityState << 1 | oldVisibilityState);
}
}
}
8 changes: 7 additions & 1 deletion assets/cubyz/shaders/chunks/occlusionTestFragment.frag
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ layout(location = 0) flat in uint chunkID;

#include "chunk_data.glsl"

layout(location = 4) uniform bool isDepth;

void main() {
chunks[chunkID].visibilityState = 1;
if(isDepth) {
chunks[chunkID].visibilityStateDepth = 1;
} else {
chunks[chunkID].visibilityState = 1;
}
}
Loading
Loading