blaze3D shaders work on both GL and Vulkan

This commit is contained in:
James Seibel
2026-05-16 15:49:41 -05:00
parent c1644ad419
commit f67d9e4e04
8 changed files with 166 additions and 86 deletions
@@ -0,0 +1,12 @@
package com.seibel.distanthorizons.core.render;
/**
* VULKAN, <br>
* OPEN_GL, <br>
*/
public enum EDhRenderApi
{
VULKAN,
OPEN_GL;
}
@@ -2,6 +2,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.render;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.jar.EPlatform;
import com.seibel.distanthorizons.core.render.EDhRenderApi;
import com.seibel.distanthorizons.core.render.EDhRenderDepth;
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
@@ -31,6 +32,7 @@ public abstract class AbstractDhRenderApiDefinition implements IBindable
public boolean useSingleIbo() { return this.useSingleIbo; }
public abstract EDhRenderDepth getRenderDepth();
public abstract EDhRenderApi getRenderApi();
//endregion
@@ -4,6 +4,11 @@ in vec2 TexCoord;
out vec4 fragColor;
layout (std140) uniform baseFragUniformBlock
{
bool uIsVulkan;
};
uniform sampler2D uSourceColorTexture;
uniform sampler2D uSourceDepthTexture;
@@ -11,11 +16,21 @@ uniform sampler2D uSourceDepthTexture;
void main()
{
fragColor = vec4(0.0);
// a fragment depth of "1" means the fragment wasn't drawn to,
// only update fragments that were drawn to
float fragmentDepth = texture(uSourceDepthTexture, TexCoord).r;
if (fragmentDepth != 1)
bool drawnTo;
if (uIsVulkan)
{
drawnTo = (fragmentDepth != 0.0f);
}
else
{
// a fragment depth of "1" means the fragment wasn't drawn to
drawnTo = (fragmentDepth != 1.0f);
}
// only update fragments that were drawn to
if (drawnTo)
{
fragColor = texture(uSourceColorTexture, TexCoord);
}
@@ -11,6 +11,8 @@ layout (std140) uniform fragUniformBlock
// inverted model view matrix and projection matrix
mat4 uDhInvMvmProj;
bool uIsVulkan;
};
uniform sampler2D uMcColorTexture;
@@ -18,16 +20,30 @@ uniform sampler2D uDhDepthTexture;
uniform sampler2D uDhColorTexture;
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
/**
* this method is shared across several shaders,
* if updated, make sure to update the other versions as well.
*/
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
{
// normalized device coordinates
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
ndc.xyz = ndc.xyz * 2.0 - 1.0;
if (uIsVulkan)
{
// Z already in [0,1], don't remap
ndc.xy = ndc.xy * 2.0 - 1.0;
}
else
{
// UV [0,1] -> NDC [-1,+1]
ndc.xyz = ndc.xyz * 2.0 - 1.0;
}
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
/**
* Used to fade out vanilla chunks so the transition
* between DH and vanilla is smoother.
@@ -21,42 +21,35 @@ layout (std140) uniform fragUniformBlock
// inverted model view matrix and projection matrix
mat4 uDhInvMvmProj;
mat4 uMcInvMvmProj;
bool uIsVulkan;
};
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
/**
* this method is shared across several shaders,
* if updated, make sure to update the other versions as well.
*/
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
{
// normalized device coordinates
vec4 ndc = vec4(
TexCoord.x, // UV [0,1]
TexCoord.y,
fragmentDepth, // depth [0,1]
1.0
);
// AKA: remap the [0,1] UV coordinates and depth value
// into the [-1,1] positions used by
// the NDC cube rendering stage
ndc.xyz = ndc.xyz * 2.0 - 1.0;
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
if (uIsVulkan)
{
// Z already in [0,1], don't remap
ndc.xy = ndc.xy * 2.0 - 1.0;
}
else
{
// UV [0,1] -> NDC [-1,+1]
ndc.xyz = ndc.xyz * 2.0 - 1.0;
}
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
// TODO vulkan
vec3 calcReversedZViewPosition(float fragmentDepth, mat4 invMvmProj)
{
// Vulkan NDC: xy in [-1,+1], z already in [0,1] — don't remap z
vec4 ndc = vec4(
TexCoord.x * 2.0 - 1.0, // UV [0,1] -> NDC [-1,+1]
TexCoord.y * 2.0 - 1.0,
fragmentDepth, // no remapping needed, this depth is already in the [0,1] range
1.0 // w=1 placeholder for matrix multiplication
);
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
/**
* Used to fade out vanilla chunks so the transition
@@ -88,19 +81,28 @@ void main()
float mcFragmentDepth = texture(uMcDepthTexture, TexCoord).r;
float dhFragmentDepth = texture(uDhDepthTexture, TexCoord).r;
vec3 dhVertexWorldPos = calcViewPosition(dhFragmentDepth, uDhInvMvmProj);
// we only want to fade vanilla rendered objects, not to the sky or LODs
bool isGround;
if (uIsVulkan)
{
isGround = (mcFragmentDepth > 0);
}
else
{
// a fragment depth of "1" means the fragment wasn't drawn to
isGround = (mcFragmentDepth < 1.0);
}
// this is a work around to prevent MC clouds rendering behind DH clouds
if (dhVertexWorldPos.y > uMaxLevelHeight)
{
fragColor = vec4(combinedMcDhColor.rgb, 0.0);
}
// // a fragment depth of "1" means the fragment wasn't drawn to,
// // we only want to fade vanilla rendered objects, not to the sky or LODs
// else if (mcFragmentDepth < 1.0)
else if (mcFragmentDepth > 0)
else if (isGround)
{
// fade based on distance from the camera
vec3 mcVertexWorldPos = calcReversedZViewPosition(mcFragmentDepth, uMcInvMvmProj);
vec3 mcVertexWorldPos = calcViewPosition(mcFragmentDepth, uMcInvMvmProj);
float mcFragmentDistance = length(mcVertexWorldPos.xzy);
@@ -40,6 +40,8 @@ layout (std140) uniform fragUniformBlock
// inverted model view matrix and projection matrix
mat4 uInvMvmProj;
bool uIsVulkan;
};
uniform sampler2D uDhDepthTexture;
@@ -50,7 +52,7 @@ uniform sampler2D uDhDepthTexture;
// method definitions //
//====================//
vec3 calcViewPosition(float fragmentDepth);
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj);
float getFarFogThickness(float dist);
float getHeightFogThickness(float dist);
@@ -84,7 +86,7 @@ void main()
if (fogDebugMode == 0)
{
// render fog based on distance from the camera
vec3 vertexWorldPos = calcViewPosition(fragmentDepth);
vec3 vertexWorldPos = calcViewPosition(fragmentDepth, uInvMvmProj);
float horizontalWorldDistance = length(vertexWorldPos.xz) * uFogScale;
float worldDistance = length(vertexWorldPos.xyz) * uFogScale;
@@ -132,12 +134,26 @@ void main()
// helper methods //
//================//
vec3 calcViewPosition(float fragmentDepth)
/**
* this method is shared across several shaders,
* if updated, make sure to update the other versions as well.
*/
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
{
// normalized device coordinates
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
ndc.xyz = ndc.xyz * 2.0 - 1.0;
if (uIsVulkan)
{
// Z already in [0,1], don't remap
ndc.xy = ndc.xy * 2.0 - 1.0;
}
else
{
// UV [0,1] -> NDC [-1,+1]
ndc.xyz = ndc.xyz * 2.0 - 1.0;
}
vec4 eyeCoord = uInvMvmProj * ndc;
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
@@ -1,21 +1,5 @@
#version 330 core
//layout (location = 1) in vec4 aColor; // RGBA_FLOAT_COLOR
//layout (location = 2) in vec3 aScale; // VEC3_SCALE
//layout (location = 3) in ivec3 aTranslateChunk; // IVEC3_SCALE
//layout (location = 4) in vec3 aTranslateSubChunk; // VEC3_SCALE
//layout (location = 5) in int aMaterial; // IRIS_MATERIAL
//uniform sampler2D /*vec4*/ uColorMap;
//uniform sampler2D /*vec3*/ uScaleMap;
//uniform sampler2D /*int*/ uTranslateChunkXMap;
//uniform sampler2D /*int*/ uTranslateChunkYMap;
//uniform sampler2D /*int*/ uTranslateChunkZMap;
//uniform sampler2D /*vec3*/ uTranslateSubChunkMap;
//uniform sampler2D /*int*/ uMaterialMap;
//
//in vec3 vPosition;
in vec3 vPosition;
in vec4 aColor; // RGBA_FLOAT_COLOR
in int aMaterial; // IRIS_MATERIAL
@@ -52,17 +36,6 @@ void main()
aScale = vec3(2);
}
// vec4 aColor = texelFetch(uColorMap, ivec2(gl_InstanceID,0), 0);
// vec3 aScale = texelFetch(uScaleMap, ivec2(gl_InstanceID,0), 0).xyz;
//
// float chunkX = int(texelFetch(uTranslateChunkXMap, ivec2(gl_InstanceID,0), 0).x);
// float chunkY = int(texelFetch(uTranslateChunkYMap, ivec2(gl_InstanceID,0), 0).x);
// float chunkZ = int(texelFetch(uTranslateChunkZMap, ivec2(gl_InstanceID,0), 0).x);
// ivec3 aTranslateChunk = ivec3(chunkX, chunkY, chunkZ);
//
// vec3 aTranslateSubChunk = texelFetch(uTranslateSubChunkMap, ivec2(gl_InstanceID,0), 0).xyz;
// int aMaterial = int(texelFetch(uMaterialMap, ivec2(gl_InstanceID,0), 0).x);
// aTranslate - moves the vertex to the boxGroup's relative position
// uOffset - moves the vertex to the boxGroup's world position
// uCameraPos - moves the vertex into camera space
@@ -21,7 +21,9 @@ layout (std140) uniform fragUniformBlock
float uFadeDistanceInBlocks;
mat4 uInvProj;
mat4 uProj;
mat4 uProj;
bool uIsVulkan;
};
uniform sampler2D uDhDepthTexture;
@@ -33,10 +35,7 @@ const float PI = 3.1415926538;
const float TAU = PI * 2.0;
vec3 unproject(vec4 pos)
{
return pos.xyz / pos.w;
}
vec3 unproject(vec4 pos) { return pos.xyz / pos.w; }
float InterleavedGradientNoise(const in vec2 pixel)
{
@@ -44,12 +43,30 @@ float InterleavedGradientNoise(const in vec2 pixel)
return fract(MAGIC.z * fract(x));
}
vec3 calcViewPosition(const in vec3 clipPos)
/**
* this method is shared across several shaders,
* if updated, make sure to update the other versions as well.
*/
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
{
vec4 viewPos = uInvProj * vec4(clipPos * 2.0 - 1.0, 1.0);
return viewPos.xyz / viewPos.w;
// normalized device coordinates
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
if (uIsVulkan)
{
// Z already in [0,1], don't remap
ndc.xy = ndc.xy * 2.0 - 1.0;
}
else
{
// UV [0,1] -> NDC [-1,+1]
ndc.xyz = ndc.xyz * 2.0 - 1.0;
}
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
float GetSpiralOcclusion(const in vec2 uv, const in vec3 viewPos, const in vec3 viewNormal)
{
float dither = InterleavedGradientNoise(gl_FragCoord.xy);
@@ -61,7 +78,8 @@ float GetSpiralOcclusion(const in vec2 uv, const in vec3 viewPos, const in vec3
float ao = 0.0;
int sampleCount = 0;
float radius = rStep;
for (int i = 0; i < clamp(uSampleCount, 1, SAMPLE_MAX); i++) {
for (int i = 0; i < clamp(uSampleCount, 1, SAMPLE_MAX); i++)
{
vec2 offset = vec2(
sin(rotatePhase),
cos(rotatePhase)
@@ -75,11 +93,27 @@ float GetSpiralOcclusion(const in vec2 uv, const in vec3 viewPos, const in vec3
sampleClipPos = saturate(sampleClipPos);
float sampleClipDepth = textureLod(uDhDepthTexture, sampleClipPos.xy, 0.0).r;
if (sampleClipDepth >= 1.0 - EPSILON) continue;
sampleClipPos.z = sampleClipDepth;
sampleViewPos = unproject(uInvProj * vec4(sampleClipPos * 2.0 - 1.0, 1.0));
if (sampleClipDepth >= 1.0 - EPSILON)
{
continue;
}
if (uIsVulkan)
{
vec4 ndc = vec4(
sampleClipPos.x * 2.0 - 1.0, // UV [0,1] -> NDC [-1,+1]
sampleClipPos.y * 2.0 - 1.0,
sampleClipDepth,
1.0 // w=1 placeholder for matrix multiplication
);
sampleViewPos = unproject(uInvProj * ndc);
}
else
{
sampleClipPos.z = sampleClipDepth;
sampleViewPos = unproject(uInvProj * vec4(sampleClipPos * 2.0 - 1.0, 1.0));
}
vec3 diff = sampleViewPos - viewPos;
float sampleDist = length(diff);
vec3 sampleNormal = diff / sampleDist;
@@ -102,10 +136,20 @@ void main()
float fragmentDepth = textureLod(uDhDepthTexture, TexCoord, 0).r;
float occlusion = 0.0;
// Do not apply to sky
if (fragmentDepth < 1.0)
bool isGround;
if (uIsVulkan)
{
vec3 viewPos = calcViewPosition(vec3(TexCoord, fragmentDepth));
isGround = (fragmentDepth > 0.0f);
}
else
{
isGround = (fragmentDepth < 1.0f);
}
// Do not apply to sky
if (isGround)
{
vec3 viewPos = calcViewPosition(fragmentDepth, uInvProj);
// fading is done to prevent banding/noise
// at super far distance