Biplanar mapping
This commit is contained in:
parent
c213acc1d4
commit
e8080bffb6
3
TODO.md
3
TODO.md
|
@ -98,8 +98,7 @@ Released as `0.0.1`: `Pre alpha 1`
|
||||||
- [ ] Merge stochastic and triplanar
|
- [ ] Merge stochastic and triplanar
|
||||||
- https://assetstore.unity.com/packages/tools/terrain/microsplat-96478
|
- https://assetstore.unity.com/packages/tools/terrain/microsplat-96478
|
||||||
- https://www.youtube.com/user/slipster216/videos
|
- https://www.youtube.com/user/slipster216/videos
|
||||||
- [ ] Biplanar
|
- [x] Biplanar
|
||||||
- Stochastic
|
|
||||||
- [ ] Distance resampling
|
- [ ] Distance resampling
|
||||||
- [ ] Tesselation
|
- [ ] Tesselation
|
||||||
- [ ] Planet scale LOD (using chunk level average)
|
- [ ] Planet scale LOD (using chunk level average)
|
||||||
|
|
BIN
resource/content/shaders/Color.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Color.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Color.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Color.vs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Sky.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Sky.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Sky.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Sky.vs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Tris.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Tris.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)
Binary file not shown.
|
@ -45,7 +45,7 @@ vec2 hash2D(vec2 s) {
|
||||||
return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453);
|
return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 textureStochastic(sampler2DArray sample, vec3 UV) {
|
vec4 textureStochasticGrad(sampler2DArray sample, vec3 UV, vec2 dx, vec2 dy) {
|
||||||
#ifdef STOCHASTIC
|
#ifdef STOCHASTIC
|
||||||
// triangular by approx 2*sqrt(3)
|
// triangular by approx 2*sqrt(3)
|
||||||
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
|
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
|
||||||
|
@ -72,12 +72,16 @@ vec4 textureStochastic(sampler2DArray sample, vec3 UV) {
|
||||||
BW_vx3 = vec3(-barry.z, 1.0 - barry.y, 1.0 - barry.x);
|
BW_vx3 = vec3(-barry.z, 1.0 - barry.y, 1.0 - barry.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 dx = dFdx(UV.xy);
|
|
||||||
vec2 dy = dFdy(UV.xy);
|
|
||||||
|
|
||||||
return textureGrad(sample, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
|
return textureGrad(sample, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
|
||||||
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
|
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
|
||||||
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
|
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
|
||||||
|
#else
|
||||||
|
return textureGrad(sample, UV, dx, dy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
vec4 textureStochastic(sampler2DArray sample, vec3 UV) {
|
||||||
|
#ifdef STOCHASTIC
|
||||||
|
return textureStochasticGrad(sample, UV, dFdx(UV.xy), dFdy(UV.xy));
|
||||||
#else
|
#else
|
||||||
return texture(sample, UV);
|
return texture(sample, UV);
|
||||||
#endif
|
#endif
|
||||||
|
@ -106,23 +110,54 @@ vec4 getTexture(sampler2DArray sample, vec2 UV) {
|
||||||
return textureStochastic(sample, vec3(UV, vs.Texture));
|
return textureStochastic(sample, vec3(UV, vs.Texture));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
vec4 getTextureGrad(sampler2DArray sample, vec2 UV, vec2 dx, vec2 dy) {
|
||||||
|
#ifdef GEOMETRY
|
||||||
|
#ifdef BLEND
|
||||||
|
vec4 colx = textureStochasticGrad(sample, vec3(UV, vs.Textures[0]), dx, dy);
|
||||||
|
if(vs.Textures[1] == vs.Textures[0]) {
|
||||||
|
return vs.Textures[2] == vs.Textures[0] ? colx :
|
||||||
|
mix(colx, textureStochasticGrad(sample, vec3(UV, vs.Textures[2]), dx, dy), vs.TextureRatio.z);
|
||||||
|
} else {
|
||||||
|
vec4 coly = textureStochasticGrad(sample, vec3(UV, vs.Textures[1]), dx, dy);
|
||||||
|
return vs.Textures[2] == vs.Textures[0] ? mix(colx, coly, vs.TextureRatio.y) : (
|
||||||
|
vs.Textures[2] == vs.Textures[1] ? mix(coly, colx, vs.TextureRatio.x) :
|
||||||
|
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochasticGrad(sample, vec3(UV, vs.Textures[2]), dx, dy) * vs.TextureRatio.z);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ?
|
||||||
|
(vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) :
|
||||||
|
(vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 2);
|
||||||
|
return textureStochasticGrad(sample, vec3(UV, vs.Textures[mainTexture]), dx, dy);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return textureStochasticGrad(sample, vec3(UV, vs.Texture), dx, dy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
vec4 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
|
vec4 getTriTexture(sampler2DArray sample, vec2 UVx, vec2 UVy, vec2 UVz, vec3 w) {
|
||||||
return getTexture(sample, crdx) * weights.x +
|
vec4 x = getTexture(sample, UVx);
|
||||||
getTexture(sample, crdy) * weights.y +
|
vec4 y = getTexture(sample, UVy);
|
||||||
getTexture(sample, crdz) * weights.z;
|
vec4 z = getTexture(sample, UVz);
|
||||||
|
return x*w.x + y*w.y + z*w.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getBiTexture(sampler2DArray sample, vec2 UVa, vec2 UVb, vec2 dxa, vec2 dxb, vec2 dya, vec2 dyb, vec2 w) {
|
||||||
|
vec4 x = getTextureGrad(sample, UVa, dxa, dya);
|
||||||
|
vec4 y = getTextureGrad(sample, UVb, dxb, dyb);
|
||||||
|
return x*w.x + y*w.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float texScale = 1. / UNIT_SIZE;
|
float texScale = 1. / UNIT_SIZE;
|
||||||
|
float transitionSpeed = 2;
|
||||||
#ifdef TRIPLANAR
|
#ifdef TRIPLANAR
|
||||||
// Triplanar
|
// Triplanar
|
||||||
float plateauSize = 0.001;
|
float plateauSize = 0.001;
|
||||||
float transitionSpeed = 2;
|
|
||||||
|
|
||||||
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
||||||
blendWeights = blendWeights - plateauSize;
|
blendWeights = blendWeights - plateauSize;
|
||||||
blendWeights = normalize(pow(max(blendWeights, 0), vec3(transitionSpeed)));
|
blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed));
|
||||||
|
blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z);
|
||||||
vec2 UVx = vs.Position_modelspace.yz * texScale;
|
vec2 UVx = vs.Position_modelspace.yz * texScale;
|
||||||
vec2 UVy = vs.Position_modelspace.zx * texScale;
|
vec2 UVy = vs.Position_modelspace.zx * texScale;
|
||||||
vec2 UVz = vs.Position_modelspace.xy * texScale;
|
vec2 UVz = vs.Position_modelspace.xy * texScale;
|
||||||
|
@ -143,6 +178,54 @@ void main() {
|
||||||
|
|
||||||
vec3 texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb;
|
vec3 texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb;
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef BIPLANAR
|
||||||
|
// Biplanar
|
||||||
|
vec3 pos = vs.Position_modelspace * texScale;
|
||||||
|
vec3 dpdx = dFdx(pos);
|
||||||
|
vec3 dpdy = dFdy(pos);
|
||||||
|
vec3 blendWeights = abs(normalize(vs.FaceNormal_modelspace));
|
||||||
|
|
||||||
|
// determine major axis (in x; yz are following axis)
|
||||||
|
ivec3 ma = (blendWeights.x>blendWeights.y && blendWeights.x>blendWeights.z) ? ivec3(0,1,2) :
|
||||||
|
(blendWeights.y>blendWeights.z) ? ivec3(1,2,0) : ivec3(2,0,1);
|
||||||
|
// determine minor axis (in x; yz are following axis)
|
||||||
|
ivec3 mi = (blendWeights.x<blendWeights.y && blendWeights.x<blendWeights.z) ? ivec3(0,1,2) :
|
||||||
|
(blendWeights.y<blendWeights.z) ? ivec3(1,2,0) : ivec3(2,0,1);
|
||||||
|
// determine median axis (in x; yz are following axis)
|
||||||
|
ivec3 me = ivec3(3) - mi - ma;
|
||||||
|
vec2 UVa = vec2(pos[ma.y], pos[ma.z]);
|
||||||
|
vec2 UVb = vec2(pos[me.y], pos[me.z]);
|
||||||
|
vec2 dxa = vec2(dpdx[ma.y], dpdx[ma.z]);
|
||||||
|
vec2 dxb = vec2(dpdx[me.y], dpdx[me.z]);
|
||||||
|
vec2 dya = vec2(dpdy[ma.y], dpdy[ma.z]);
|
||||||
|
vec2 dyb = vec2(dpdy[me.y], dpdy[me.z]);
|
||||||
|
|
||||||
|
// blend factors
|
||||||
|
vec2 w = vec2(blendWeights[ma.x],blendWeights[me.x]);
|
||||||
|
w = clamp((w-0.5773)/(1.0-0.5773), 0.0, 1.0);
|
||||||
|
w = pow(w, vec2(transitionSpeed/8));
|
||||||
|
w = w / (w.x + w.y);
|
||||||
|
|
||||||
|
vec4 tex = getBiTexture(TextureAtlas, UVa, UVb, dxa, dxb, dya, dyb, w);
|
||||||
|
|
||||||
|
#ifdef PBR
|
||||||
|
// Whiteout normal blend
|
||||||
|
vec3 texNa = expand(getTextureGrad(NormalAtlas, UVa, dxa, dya).rgb);
|
||||||
|
vec3 texNb = expand(getTextureGrad(NormalAtlas, UVb, dxb, dyb).rgb);
|
||||||
|
|
||||||
|
// Swizzle world normals into tangent space and apply Whiteout blend
|
||||||
|
texNa = normalize(vec3(texNa.xy + vs.FaceNormal_worldspace.zy, abs(texNa.z) * vs.FaceNormal_worldspace.x).zyx * blendWeights.x +
|
||||||
|
vec3(texNa.xy + vs.FaceNormal_worldspace.xz, abs(texNa.z) * vs.FaceNormal_worldspace.y).xzy * blendWeights.y +
|
||||||
|
vec3(texNa.xy + vs.FaceNormal_worldspace.xy, abs(texNa.z) * vs.FaceNormal_worldspace.z).xyz * blendWeights.z);
|
||||||
|
texNb = normalize(vec3(texNb.xy + vs.FaceNormal_worldspace.zy, abs(texNb.z) * vs.FaceNormal_worldspace.x).zyx * blendWeights.x +
|
||||||
|
vec3(texNb.xy + vs.FaceNormal_worldspace.xz, abs(texNb.z) * vs.FaceNormal_worldspace.y).xzy * blendWeights.y +
|
||||||
|
vec3(texNb.xy + vs.FaceNormal_worldspace.xy, abs(texNb.z) * vs.FaceNormal_worldspace.z).xyz * blendWeights.z);
|
||||||
|
// Swizzle tangent normals to match world orientation and biblend
|
||||||
|
vec3 worldNormal = normalize((texNa * w.x + texNb * w.y) / (w.x + w.y));
|
||||||
|
|
||||||
|
vec3 texHOS = getBiTexture(HOSAtlas, UVa, UVb, dxa, dxb, dya, dyb, w).rgb;
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
// Cheap planar
|
// Cheap planar
|
||||||
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
||||||
|
@ -152,8 +235,7 @@ void main() {
|
||||||
vec4 tex = getTexture(TextureAtlas, UV);
|
vec4 tex = getTexture(TextureAtlas, UV);
|
||||||
#ifdef PBR
|
#ifdef PBR
|
||||||
vec3 texN = expand(getTexture(NormalAtlas, UV).rgb);
|
vec3 texN = expand(getTexture(NormalAtlas, UV).rgb);
|
||||||
// Swizzle world normals into tangent space and apply Whiteout blend
|
// Swizzle tangent normals to match world orientation
|
||||||
// Swizzle tangent normals to match world orientation and triblend
|
|
||||||
vec3 worldNormal = normalize(vec3(texN.xy + vs.FaceNormal_worldspace.zy, abs(texN.z) * vs.FaceNormal_worldspace.x).zyx * blendWeights.x +
|
vec3 worldNormal = normalize(vec3(texN.xy + vs.FaceNormal_worldspace.zy, abs(texN.z) * vs.FaceNormal_worldspace.x).zyx * blendWeights.x +
|
||||||
vec3(texN.xy + vs.FaceNormal_worldspace.xz, abs(texN.z) * vs.FaceNormal_worldspace.y).xzy * blendWeights.y +
|
vec3(texN.xy + vs.FaceNormal_worldspace.xz, abs(texN.z) * vs.FaceNormal_worldspace.y).xzy * blendWeights.y +
|
||||||
vec3(texN.xy + vs.FaceNormal_worldspace.xy, abs(texN.z) * vs.FaceNormal_worldspace.z).xyz * blendWeights.z);
|
vec3(texN.xy + vs.FaceNormal_worldspace.xy, abs(texN.z) * vs.FaceNormal_worldspace.z).xyz * blendWeights.z);
|
||||||
|
@ -161,6 +243,7 @@ void main() {
|
||||||
vec3 texHOS = getTexture(HOSAtlas, UV).rgb;
|
vec3 texHOS = getTexture(HOSAtlas, UV).rgb;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Colors
|
// Colors
|
||||||
#ifdef PBR
|
#ifdef PBR
|
||||||
|
@ -173,8 +256,8 @@ void main() {
|
||||||
|
|
||||||
// Light emission properties
|
// Light emission properties
|
||||||
// You probably want to put them as uniforms
|
// You probably want to put them as uniforms
|
||||||
vec3 LightColor = vec3(1, 0.9, 0.9);
|
vec3 LightColor = vec3(1, 0.9, 0.75);
|
||||||
float LightPower = 1.2f;
|
float LightPower = 1.25f;
|
||||||
|
|
||||||
// Distance to the light
|
// Distance to the light
|
||||||
float distance = 1.0f;//length( LightPosition_worldspace - Position_worldspace );
|
float distance = 1.0f;//length( LightPosition_worldspace - Position_worldspace );
|
||||||
|
@ -214,7 +297,7 @@ void main() {
|
||||||
#else
|
#else
|
||||||
color = tex;
|
color = tex;
|
||||||
#endif
|
#endif
|
||||||
#if FOG
|
#ifdef FOG
|
||||||
float ratio = exp(vs.Depth * 0.69)-1;
|
float ratio = exp(vs.Depth * 0.69)-1;
|
||||||
color = mix(color, vec4(pow(FogColor, vec3(2.2)), 1), clamp(ratio, 0, 1));
|
color = mix(color, vec4(pow(FogColor, vec3(2.2)), 1), clamp(ratio, 0, 1));
|
||||||
#endif
|
#endif
|
||||||
|
|
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.gs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.gs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.ins.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.ins.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.ins.gs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.ins.gs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.ins.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.ins.vs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.vs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.ins.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.ins.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.ins.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.ins.vs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.spv (Stored with Git LFS)
Binary file not shown.
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
layout (constant_id = 0) const bool FOG = true;
|
layout (constant_id = 0) const bool FOG = true;
|
||||||
layout (constant_id = 1) const bool PBR = true;
|
layout (constant_id = 1) const bool PBR = true;
|
||||||
layout (constant_id = 2) const bool TRIPLANAR = false;
|
layout (constant_id = 2) const bool BIPLANAR = false;
|
||||||
layout (constant_id = 3) const bool STOCHASTIC = false;
|
layout (constant_id = 3) const bool TRIPLANAR = false;
|
||||||
layout (constant_id = 4) const bool BLEND = true;
|
layout (constant_id = 4) const bool STOCHASTIC = false;
|
||||||
|
layout (constant_id = 5) const bool BLEND = true;
|
||||||
// ...
|
// ...
|
||||||
layout (constant_id = 16) const int UNIT_SIZE = 8;
|
layout (constant_id = 16) const int UNIT_SIZE = 8;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ vec2 hash2D(vec2 s) {
|
||||||
return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453);
|
return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 textureStochastic(sampler2DArray smpl, vec3 UV) {
|
vec4 textureStochasticGrad(sampler2DArray smpl, vec3 UV, vec2 dx, vec2 dy) {
|
||||||
if(STOCHASTIC) {
|
if(STOCHASTIC) {
|
||||||
// triangular by approx 2*sqrt(3)
|
// triangular by approx 2*sqrt(3)
|
||||||
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
|
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
|
||||||
|
@ -81,12 +82,16 @@ if(STOCHASTIC) {
|
||||||
BW_vx3 = vec3(-barry.z, 1.0 - barry.y, 1.0 - barry.x);
|
BW_vx3 = vec3(-barry.z, 1.0 - barry.y, 1.0 - barry.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 dx = dFdx(UV.xy);
|
|
||||||
vec2 dy = dFdy(UV.xy);
|
|
||||||
|
|
||||||
return textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
|
return textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
|
||||||
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
|
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
|
||||||
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
|
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
|
||||||
|
} else {
|
||||||
|
return textureGrad(smpl, UV, dx, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec4 textureStochastic(sampler2DArray smpl, vec3 UV) {
|
||||||
|
if(STOCHASTIC) {
|
||||||
|
return textureStochasticGrad(smpl, UV, dFdx(UV.xy), dFdy(UV.xy));
|
||||||
} else {
|
} else {
|
||||||
return texture(smpl, UV);
|
return texture(smpl, UV);
|
||||||
}
|
}
|
||||||
|
@ -115,26 +120,57 @@ if(BLEND) {
|
||||||
return textureStochastic(smpl, vec3(UV, vs.Texture));
|
return textureStochastic(smpl, vec3(UV, vs.Texture));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
vec4 getTextureGrad(sampler2DArray smpl, vec2 UV, vec2 dx, vec2 dy) {
|
||||||
|
#ifdef GEOMETRY
|
||||||
|
if(BLEND) {
|
||||||
|
vec4 colx = textureStochasticGrad(smpl, vec3(UV, vs.Textures[0]), dx, dy);
|
||||||
|
if(vs.Textures[1] == vs.Textures[0]) {
|
||||||
|
return vs.Textures[2] == vs.Textures[0] ? colx :
|
||||||
|
mix(colx, textureStochasticGrad(smpl, vec3(UV, vs.Textures[2]), dx, dy), vs.TextureRatio.z);
|
||||||
|
} else {
|
||||||
|
vec4 coly = textureStochasticGrad(smpl, vec3(UV, vs.Textures[1]), dx, dy);
|
||||||
|
return vs.Textures[2] == vs.Textures[0] ? mix(colx, coly, vs.TextureRatio.y) : (
|
||||||
|
vs.Textures[2] == vs.Textures[1] ? mix(coly, colx, vs.TextureRatio.x) :
|
||||||
|
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochasticGrad(smpl, vec3(UV, vs.Textures[2]), dx, dy) * vs.TextureRatio.z);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ?
|
||||||
|
(vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) :
|
||||||
|
(vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 2);
|
||||||
|
return textureStochasticGrad(smpl, vec3(UV, vs.Textures[mainTexture]), dx, dy);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return textureStochasticGrad(smpl, vec3(UV, vs.Texture), dx, dy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
vec4 getTriTexture(sampler2DArray smpl, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
|
vec4 getTriTexture(sampler2DArray smpl, vec2 UVx, vec2 UVy, vec2 UVz, vec3 w) {
|
||||||
return getTexture(smpl, crdx) * weights.x +
|
vec4 x = getTexture(smpl, UVx);
|
||||||
getTexture(smpl, crdy) * weights.y +
|
vec4 y = getTexture(smpl, UVy);
|
||||||
getTexture(smpl, crdz) * weights.z;
|
vec4 z = getTexture(smpl, UVz);
|
||||||
|
return x*w.x + y*w.y + z*w.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getBiTexture(sampler2DArray smpl, vec2 UVa, vec2 UVb, vec2 dxa, vec2 dxb, vec2 dya, vec2 dyb, vec2 w) {
|
||||||
|
vec4 x = getTextureGrad(smpl, UVa, dxa, dya);
|
||||||
|
vec4 y = getTextureGrad(smpl, UVb, dxb, dyb);
|
||||||
|
return x*w.x + y*w.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float texScale = 1. / UNIT_SIZE;
|
float texScale = 1. / UNIT_SIZE;
|
||||||
|
float transitionSpeed = 2;
|
||||||
vec4 tex;
|
vec4 tex;
|
||||||
vec3 worldNormal, texHOS;
|
vec3 worldNormal, texHOS;
|
||||||
|
|
||||||
if(TRIPLANAR) {
|
if(TRIPLANAR) {
|
||||||
// Triplanar
|
// Triplanar
|
||||||
float plateauSize = 0.001;
|
float plateauSize = 0.001;
|
||||||
float transitionSpeed = 2;
|
|
||||||
|
|
||||||
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
||||||
blendWeights = blendWeights - plateauSize;
|
blendWeights = blendWeights - plateauSize;
|
||||||
blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed));
|
blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed));
|
||||||
|
blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z);
|
||||||
vec2 UVx = vs.Position_modelspace.yz * texScale;
|
vec2 UVx = vs.Position_modelspace.yz * texScale;
|
||||||
vec2 UVy = vs.Position_modelspace.zx * texScale;
|
vec2 UVy = vs.Position_modelspace.zx * texScale;
|
||||||
vec2 UVz = vs.Position_modelspace.xy * texScale;
|
vec2 UVz = vs.Position_modelspace.xy * texScale;
|
||||||
|
@ -155,6 +191,53 @@ if(PBR) {
|
||||||
|
|
||||||
texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb;
|
texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb;
|
||||||
}
|
}
|
||||||
|
} else if(BIPLANAR) {
|
||||||
|
// Biplanar
|
||||||
|
vec3 pos = vs.Position_modelspace * texScale;
|
||||||
|
vec3 dpdx = dFdx(pos);
|
||||||
|
vec3 dpdy = dFdy(pos);
|
||||||
|
vec3 blendWeights = abs(normalize(vs.FaceNormal_modelspace));
|
||||||
|
|
||||||
|
// determine major axis (in x; yz are following axis)
|
||||||
|
ivec3 ma = (blendWeights.x>blendWeights.y && blendWeights.x>blendWeights.z) ? ivec3(0,1,2) :
|
||||||
|
(blendWeights.y>blendWeights.z) ? ivec3(1,2,0) : ivec3(2,0,1);
|
||||||
|
// determine minor axis (in x; yz are following axis)
|
||||||
|
ivec3 mi = (blendWeights.x<blendWeights.y && blendWeights.x<blendWeights.z) ? ivec3(0,1,2) :
|
||||||
|
(blendWeights.y<blendWeights.z) ? ivec3(1,2,0) : ivec3(2,0,1);
|
||||||
|
// determine median axis (in x; yz are following axis)
|
||||||
|
ivec3 me = ivec3(3) - mi - ma;
|
||||||
|
vec2 UVa = vec2(pos[ma.y], pos[ma.z]);
|
||||||
|
vec2 UVb = vec2(pos[me.y], pos[me.z]);
|
||||||
|
vec2 dxa = vec2(dpdx[ma.y], dpdx[ma.z]);
|
||||||
|
vec2 dxb = vec2(dpdx[me.y], dpdx[me.z]);
|
||||||
|
vec2 dya = vec2(dpdy[ma.y], dpdy[ma.z]);
|
||||||
|
vec2 dyb = vec2(dpdy[me.y], dpdy[me.z]);
|
||||||
|
|
||||||
|
// blend factors
|
||||||
|
vec2 w = vec2(blendWeights[ma.x],blendWeights[me.x]);
|
||||||
|
w = clamp((w-0.5773)/(1.0-0.5773), 0.0, 1.0);
|
||||||
|
w = pow(w, vec2(transitionSpeed/8.0));
|
||||||
|
w = w / (w.x + w.y);
|
||||||
|
|
||||||
|
tex = getBiTexture(TextureAtlas, UVa, UVb, dxa, dxb, dya, dyb, w);
|
||||||
|
|
||||||
|
if(PBR) {
|
||||||
|
// Whiteout normal blend
|
||||||
|
vec3 texNa = expand(getTextureGrad(NormalAtlas, UVa, dxa, dya).rgb);
|
||||||
|
vec3 texNb = expand(getTextureGrad(NormalAtlas, UVb, dxb, dyb).rgb);
|
||||||
|
|
||||||
|
// Swizzle world normals into tangent space and apply Whiteout blend
|
||||||
|
texNa = normalize(vec3(texNa.xy + vs.FaceNormal_worldspace.zy, abs(texNa.z) * vs.FaceNormal_worldspace.x).zyx * blendWeights.x +
|
||||||
|
vec3(texNa.xy + vs.FaceNormal_worldspace.xz, abs(texNa.z) * vs.FaceNormal_worldspace.y).xzy * blendWeights.y +
|
||||||
|
vec3(texNa.xy + vs.FaceNormal_worldspace.xy, abs(texNa.z) * vs.FaceNormal_worldspace.z).xyz * blendWeights.z);
|
||||||
|
texNb = normalize(vec3(texNb.xy + vs.FaceNormal_worldspace.zy, abs(texNb.z) * vs.FaceNormal_worldspace.x).zyx * blendWeights.x +
|
||||||
|
vec3(texNb.xy + vs.FaceNormal_worldspace.xz, abs(texNb.z) * vs.FaceNormal_worldspace.y).xzy * blendWeights.y +
|
||||||
|
vec3(texNb.xy + vs.FaceNormal_worldspace.xy, abs(texNb.z) * vs.FaceNormal_worldspace.z).xyz * blendWeights.z);
|
||||||
|
// Swizzle tangent normals to match world orientation and biblend
|
||||||
|
worldNormal = normalize((texNa * w.x + texNb * w.y) / (w.x + w.y));
|
||||||
|
|
||||||
|
texHOS = getBiTexture(HOSAtlas, UVa, UVb, dxa, dxb, dya, dyb, w).rgb;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Cheap planar
|
// Cheap planar
|
||||||
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
layout (constant_id = 0) const bool FOG = true;
|
layout (constant_id = 0) const bool FOG = true;
|
||||||
layout (constant_id = 1) const bool PBR = true;
|
layout (constant_id = 1) const bool PBR = true;
|
||||||
// FS spe
|
// FS spe
|
||||||
layout (constant_id = 5) const bool DO_CURVATURE = false;
|
layout (constant_id = 8) const bool DO_CURVATURE = false;
|
||||||
layout (constant_id = 6) const bool CURV_DEPTH = true;
|
layout (constant_id = 9) const bool CURV_DEPTH = true;
|
||||||
|
|
||||||
layout (binding = 0) uniform UniformBufferObject {
|
layout (binding = 0) uniform UniformBufferObject {
|
||||||
mat4 view;
|
mat4 view;
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
renderer.textureQuality = config["render"]["texture_quality"].value_or(renderer.textureQuality);
|
renderer.textureQuality = config["render"]["texture_quality"].value_or(renderer.textureQuality);
|
||||||
renderer.textureSharpness = config["render"]["texture_angular_quality"].value_or(renderer.textureSharpness);
|
renderer.textureSharpness = config["render"]["texture_angular_quality"].value_or(renderer.textureSharpness);
|
||||||
renderer.voxel.pbr = config["render"]["pbr"].value_or(renderer.voxel.pbr);
|
renderer.voxel.pbr = config["render"]["pbr"].value_or(renderer.voxel.pbr);
|
||||||
renderer.voxel.triplanar = config["render"]["triplanar"].value_or(renderer.voxel.triplanar);
|
renderer.voxel.planar = static_cast<render::Planar>(config["render"]["planar"].value_or(static_cast<int>(renderer.voxel.planar)));
|
||||||
renderer.voxel.stochastic = config["render"]["stochastic"].value_or(renderer.voxel.stochastic);
|
renderer.voxel.stochastic = config["render"]["stochastic"].value_or(renderer.voxel.stochastic);
|
||||||
renderer.voxel.geometry = config["render"]["geometry"].value_or(renderer.voxel.geometry);
|
renderer.voxel.geometry = config["render"]["geometry"].value_or(renderer.voxel.geometry);
|
||||||
renderer.voxel.blend = config["render"]["blend"].value_or(renderer.voxel.blend);
|
renderer.voxel.blend = config["render"]["blend"].value_or(renderer.voxel.blend);
|
||||||
|
@ -120,7 +120,7 @@ public:
|
||||||
{"texture_quality", renderer.textureQuality},
|
{"texture_quality", renderer.textureQuality},
|
||||||
{"texture_angular_quality", renderer.textureSharpness},
|
{"texture_angular_quality", renderer.textureSharpness},
|
||||||
{"pbr", renderer.voxel.pbr},
|
{"pbr", renderer.voxel.pbr},
|
||||||
{"triplanar", renderer.voxel.triplanar},
|
{"planar", static_cast<int>(renderer.voxel.planar)},
|
||||||
{"stochastic", renderer.voxel.stochastic},
|
{"stochastic", renderer.voxel.stochastic},
|
||||||
{"geometry", renderer.voxel.geometry},
|
{"geometry", renderer.voxel.geometry},
|
||||||
{"blend", renderer.voxel.blend},
|
{"blend", renderer.voxel.blend},
|
||||||
|
|
|
@ -15,12 +15,18 @@ namespace render {
|
||||||
class Model;
|
class Model;
|
||||||
class LodModel;
|
class LodModel;
|
||||||
|
|
||||||
|
enum class Planar {
|
||||||
|
Cheap = 1,
|
||||||
|
Biplanar = 2,
|
||||||
|
Triplanar = 3
|
||||||
|
};
|
||||||
|
|
||||||
/// Pass options
|
/// Pass options
|
||||||
struct passOptions {
|
struct passOptions {
|
||||||
/// Apply light properties
|
/// Apply light properties
|
||||||
bool pbr = true;
|
bool pbr = true;
|
||||||
/// Triplanar texture mapping
|
/// Texture mapping
|
||||||
bool triplanar = false;
|
Planar planar = Planar::Cheap;
|
||||||
/// Transform texture UV
|
/// Transform texture UV
|
||||||
bool stochastic = false;
|
bool stochastic = false;
|
||||||
/// Active geometry pass
|
/// Active geometry pass
|
||||||
|
|
|
@ -16,7 +16,67 @@ UI::UI() {
|
||||||
// Setup Dear ImGui context
|
// Setup Dear ImGui context
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
ImGui::StyleColorsDark();
|
{
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
ImGuiStyle &style = ImGui::GetStyle();
|
||||||
|
style.TabRounding = 1;
|
||||||
|
style.WindowRounding = 2;
|
||||||
|
style.GrabRounding = 2;
|
||||||
|
style.FrameRounding = 4;
|
||||||
|
style.ScrollbarRounding = 4;
|
||||||
|
style.WindowMenuButtonPosition = ImGuiDir_Right;
|
||||||
|
|
||||||
|
// Purple dark theme
|
||||||
|
/*ImVec4* colors = style.Colors;
|
||||||
|
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||||
|
colors[ImGuiCol_TextDisabled] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f);
|
||||||
|
colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
|
||||||
|
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||||
|
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
||||||
|
colors[ImGuiCol_Border] = ImVec4(0.53f, 0.46f, 0.54f, 0.50f);
|
||||||
|
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||||
|
colors[ImGuiCol_FrameBg] = ImVec4(0.38f, 0.34f, 0.40f, 0.54f);
|
||||||
|
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.83f, 0.26f, 0.98f, 0.40f);
|
||||||
|
colors[ImGuiCol_FrameBgActive] = ImVec4(0.73f, 0.26f, 0.98f, 0.67f);
|
||||||
|
colors[ImGuiCol_TitleBg] = ImVec4(0.14f, 0.00f, 0.21f, 1.00f);
|
||||||
|
colors[ImGuiCol_TitleBgActive] = ImVec4(0.39f, 0.16f, 0.48f, 1.00f);
|
||||||
|
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.13f, 0.00f, 0.21f, 0.51f);
|
||||||
|
colors[ImGuiCol_MenuBarBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
|
||||||
|
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
|
||||||
|
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
|
||||||
|
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
|
||||||
|
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
|
||||||
|
colors[ImGuiCol_CheckMark] = ImVec4(0.74f, 0.27f, 0.83f, 1.00f);
|
||||||
|
colors[ImGuiCol_SliderGrab] = ImVec4(0.55f, 0.21f, 0.80f, 1.00f);
|
||||||
|
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.75f, 0.27f, 0.83f, 1.00f);
|
||||||
|
colors[ImGuiCol_Button] = ImVec4(0.85f, 0.26f, 0.98f, 0.40f);
|
||||||
|
colors[ImGuiCol_ButtonHovered] = ImVec4(0.76f, 0.26f, 0.98f, 1.00f);
|
||||||
|
colors[ImGuiCol_ButtonActive] = ImVec4(0.63f, 0.06f, 0.98f, 1.00f);
|
||||||
|
colors[ImGuiCol_Header] = ImVec4(0.81f, 0.26f, 0.98f, 0.31f);
|
||||||
|
colors[ImGuiCol_HeaderHovered] = ImVec4(0.84f, 0.26f, 0.98f, 0.80f);
|
||||||
|
colors[ImGuiCol_HeaderActive] = ImVec4(0.79f, 0.26f, 0.98f, 1.00f);
|
||||||
|
colors[ImGuiCol_Separator] = ImVec4(0.38f, 0.35f, 0.40f, 0.54f);
|
||||||
|
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.64f, 0.10f, 0.75f, 0.78f);
|
||||||
|
colors[ImGuiCol_SeparatorActive] = ImVec4(0.53f, 0.10f, 0.75f, 1.00f);
|
||||||
|
colors[ImGuiCol_ResizeGrip] = ImVec4(0.77f, 0.26f, 0.98f, 0.25f);
|
||||||
|
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.83f, 0.26f, 0.98f, 0.67f);
|
||||||
|
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.76f, 0.26f, 0.98f, 0.95f);
|
||||||
|
colors[ImGuiCol_Tab] = ImVec4(0.48f, 0.18f, 0.58f, 0.86f);
|
||||||
|
colors[ImGuiCol_TabHovered] = ImVec4(0.79f, 0.26f, 0.98f, 0.80f);
|
||||||
|
colors[ImGuiCol_TabActive] = ImVec4(0.54f, 0.20f, 0.68f, 1.00f);
|
||||||
|
colors[ImGuiCol_TabUnfocused] = ImVec4(0.10f, 0.07f, 0.15f, 0.97f);
|
||||||
|
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.22f, 0.14f, 0.42f, 1.00f);
|
||||||
|
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||||
|
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||||
|
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||||
|
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
||||||
|
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.55f, 0.26f, 0.98f, 0.35f);
|
||||||
|
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||||
|
colors[ImGuiCol_NavHighlight] = ImVec4(0.55f, 0.26f, 0.98f, 1.00f);
|
||||||
|
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||||
|
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
||||||
|
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);*/
|
||||||
|
}
|
||||||
|
|
||||||
for(auto file: std::filesystem::directory_iterator("content/textures/")) {
|
for(auto file: std::filesystem::directory_iterator("content/textures/")) {
|
||||||
if(file.is_directory() && file.path().filename() != "ui")
|
if(file.is_directory() && file.path().filename() != "ui")
|
||||||
|
@ -87,10 +147,13 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
|
||||||
|
|
||||||
{
|
{
|
||||||
bool changeRenderer = false;
|
bool changeRenderer = false;
|
||||||
|
{
|
||||||
|
int planarIdx = static_cast<int>(options.renderer.voxel.planar) - 1;
|
||||||
|
changeRenderer |= ImGui::Combo("Mapping", &planarIdx, "Cheap\0Biplanar\0Triplanar\0");
|
||||||
|
options.renderer.voxel.planar = static_cast<render::Planar>(planarIdx + 1);
|
||||||
|
}
|
||||||
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.voxel.pbr);
|
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.voxel.pbr);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.voxel.triplanar);
|
|
||||||
ImGui::SameLine();
|
|
||||||
changeRenderer |= ImGui::Checkbox("Stochastic", &options.renderer.voxel.stochastic);
|
changeRenderer |= ImGui::Checkbox("Stochastic", &options.renderer.voxel.stochastic);
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
ImGui::SetTooltip("Hide textures tiling\nMay cause visible inconsistances on chunk borders");
|
ImGui::SetTooltip("Hide textures tiling\nMay cause visible inconsistances on chunk borders");
|
||||||
|
|
|
@ -8,7 +8,9 @@ VoxelProgram::VoxelProgram(const VoxelProgram::options& opts, std::vector<std::s
|
||||||
|
|
||||||
if (opts.pbr)
|
if (opts.pbr)
|
||||||
flags.emplace_back("PBR");
|
flags.emplace_back("PBR");
|
||||||
if (opts.triplanar)
|
if (opts.planar == render::Planar::Biplanar)
|
||||||
|
flags.emplace_back("BIPLANAR");
|
||||||
|
if (opts.planar == render::Planar::Triplanar)
|
||||||
flags.emplace_back("TRIPLANAR");
|
flags.emplace_back("TRIPLANAR");
|
||||||
if (opts.stochastic)
|
if (opts.stochastic)
|
||||||
flags.emplace_back("STOCHASTIC");
|
flags.emplace_back("STOCHASTIC");
|
||||||
|
|
|
@ -384,6 +384,60 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
multisampling.alphaToCoverageEnable = VK_FALSE;
|
multisampling.alphaToCoverageEnable = VK_FALSE;
|
||||||
multisampling.alphaToOneEnable = VK_FALSE;
|
multisampling.alphaToOneEnable = VK_FALSE;
|
||||||
|
|
||||||
|
struct SpeData {
|
||||||
|
bool fog;
|
||||||
|
bool pbr;
|
||||||
|
bool biplanar;
|
||||||
|
bool triplanar;
|
||||||
|
bool stochastic;
|
||||||
|
bool blend;
|
||||||
|
bool curvature;
|
||||||
|
bool curv_depth;
|
||||||
|
int32_t unitSize;
|
||||||
|
} speData;
|
||||||
|
std::array<VkSpecializationMapEntry, 9> speIndex;
|
||||||
|
speData.fog = options.voxel.fog;
|
||||||
|
speIndex[0].constantID = 0;
|
||||||
|
speIndex[0].offset = offsetof(SpeData, fog);
|
||||||
|
speIndex[0].size = sizeof(SpeData::fog);
|
||||||
|
speData.pbr = options.voxel.pbr;
|
||||||
|
speIndex[1].constantID = 1;
|
||||||
|
speIndex[1].offset = offsetof(SpeData, pbr);
|
||||||
|
speIndex[1].size = sizeof(SpeData::pbr);
|
||||||
|
speData.biplanar = options.voxel.planar == render::Planar::Biplanar;
|
||||||
|
speIndex[2].constantID = 2;
|
||||||
|
speIndex[2].offset = offsetof(SpeData, biplanar);
|
||||||
|
speIndex[2].size = sizeof(SpeData::biplanar);
|
||||||
|
speData.triplanar = options.voxel.planar == render::Planar::Triplanar;
|
||||||
|
speIndex[3].constantID = 3;
|
||||||
|
speIndex[3].offset = offsetof(SpeData, triplanar);
|
||||||
|
speIndex[3].size = sizeof(SpeData::triplanar);
|
||||||
|
speData.stochastic = options.voxel.stochastic;
|
||||||
|
speIndex[4].constantID = 4;
|
||||||
|
speIndex[4].offset = offsetof(SpeData, stochastic);
|
||||||
|
speIndex[4].size = sizeof(SpeData::stochastic);
|
||||||
|
speData.blend = options.voxel.blend;
|
||||||
|
speIndex[5].constantID = 5;
|
||||||
|
speIndex[5].offset = offsetof(SpeData, blend);
|
||||||
|
speIndex[5].size = sizeof(SpeData::blend);
|
||||||
|
speData.curvature = options.voxel.curvature;
|
||||||
|
speIndex[6].constantID = 8;
|
||||||
|
speIndex[6].offset = offsetof(SpeData, curvature);
|
||||||
|
speIndex[6].size = sizeof(SpeData::curvature);
|
||||||
|
speData.curv_depth = options.voxel.curv_depth;
|
||||||
|
speIndex[7].constantID = 9;
|
||||||
|
speIndex[7].offset = offsetof(SpeData, curv_depth);
|
||||||
|
speIndex[7].size = sizeof(SpeData::curv_depth);
|
||||||
|
speData.unitSize = 8; //TODO: load from world.voxel_density
|
||||||
|
speIndex[8].constantID = 16;
|
||||||
|
speIndex[8].offset = offsetof(SpeData, unitSize);
|
||||||
|
speIndex[8].size = sizeof(SpeData::unitSize);
|
||||||
|
VkSpecializationInfo voxelSpecialization{};
|
||||||
|
voxelSpecialization.dataSize = sizeof(SpeData);
|
||||||
|
voxelSpecialization.pData = &speData;
|
||||||
|
voxelSpecialization.mapEntryCount = speIndex.size();
|
||||||
|
voxelSpecialization.pMapEntries = speIndex.data();
|
||||||
|
|
||||||
{ // World pipeline
|
{ // World pipeline
|
||||||
VkPushConstantRange pushRange{};
|
VkPushConstantRange pushRange{};
|
||||||
pushRange.offset = 0;
|
pushRange.offset = 0;
|
||||||
|
@ -391,57 +445,8 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
setLayout(worldPass, {voxelDescriptorSet}, {pushRange});
|
setLayout(worldPass, {voxelDescriptorSet}, {pushRange});
|
||||||
|
|
||||||
struct SpeData {
|
|
||||||
bool fog;
|
|
||||||
bool pbr;
|
|
||||||
bool triplanar;
|
|
||||||
bool stochastic;
|
|
||||||
bool blend;
|
|
||||||
bool curvature;
|
|
||||||
bool curv_depth;
|
|
||||||
int32_t unitSize;
|
|
||||||
} speData;
|
|
||||||
std::array<VkSpecializationMapEntry, 8> speIndex;
|
|
||||||
speData.fog = options.voxel.fog;
|
|
||||||
speIndex[0].constantID = 0;
|
|
||||||
speIndex[0].offset = offsetof(SpeData, fog);
|
|
||||||
speIndex[0].size = sizeof(SpeData::fog);
|
|
||||||
speData.pbr = options.voxel.pbr;
|
|
||||||
speIndex[1].constantID = 1;
|
|
||||||
speIndex[1].offset = offsetof(SpeData, pbr);
|
|
||||||
speIndex[1].size = sizeof(SpeData::pbr);
|
|
||||||
speData.triplanar = options.voxel.triplanar;
|
|
||||||
speIndex[2].constantID = 2;
|
|
||||||
speIndex[2].offset = offsetof(SpeData, triplanar);
|
|
||||||
speIndex[2].size = sizeof(SpeData::triplanar);
|
|
||||||
speData.stochastic = options.voxel.stochastic;
|
|
||||||
speIndex[3].constantID = 3;
|
|
||||||
speIndex[3].offset = offsetof(SpeData, stochastic);
|
|
||||||
speIndex[3].size = sizeof(SpeData::stochastic);
|
|
||||||
speData.blend = options.voxel.blend;
|
|
||||||
speIndex[4].constantID = 4;
|
|
||||||
speIndex[4].offset = offsetof(SpeData, blend);
|
|
||||||
speIndex[4].size = sizeof(SpeData::blend);
|
|
||||||
speData.curvature = options.voxel.curvature;
|
|
||||||
speIndex[5].constantID = 5;
|
|
||||||
speIndex[5].offset = offsetof(SpeData, curvature);
|
|
||||||
speIndex[5].size = sizeof(SpeData::curvature);
|
|
||||||
speData.curv_depth = options.voxel.curv_depth;
|
|
||||||
speIndex[6].constantID = 6;
|
|
||||||
speIndex[6].offset = offsetof(SpeData, curv_depth);
|
|
||||||
speIndex[6].size = sizeof(SpeData::curv_depth);
|
|
||||||
speData.unitSize = 8; //TODO: load from world.voxel_density
|
|
||||||
speIndex[7].constantID = 16;
|
|
||||||
speIndex[7].offset = offsetof(SpeData, unitSize);
|
|
||||||
speIndex[7].size = sizeof(SpeData::unitSize);
|
|
||||||
VkSpecializationInfo specialization{};
|
|
||||||
specialization.dataSize = sizeof(SpeData);
|
|
||||||
specialization.pData = &speData;
|
|
||||||
specialization.mapEntryCount = speIndex.size();
|
|
||||||
specialization.pMapEntries = speIndex.data();
|
|
||||||
|
|
||||||
auto withGeometry = options.voxel.geometry && info.features.geometryShader;
|
auto withGeometry = options.voxel.geometry && info.features.geometryShader;
|
||||||
auto shaderStages = setShaders(worldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &specialization);
|
auto shaderStages = setShaders(worldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &voxelSpecialization);
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
@ -530,57 +535,8 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
setLayout(transparentWorldPass, {voxelDescriptorSet}, {pushRange});
|
setLayout(transparentWorldPass, {voxelDescriptorSet}, {pushRange});
|
||||||
|
|
||||||
struct SpeData {
|
|
||||||
bool fog;
|
|
||||||
bool pbr;
|
|
||||||
bool triplanar;
|
|
||||||
bool stochastic;
|
|
||||||
bool blend;
|
|
||||||
bool curvature;
|
|
||||||
bool curv_depth;
|
|
||||||
int32_t unitSize;
|
|
||||||
} speData;
|
|
||||||
std::array<VkSpecializationMapEntry, 8> speIndex;
|
|
||||||
speData.fog = options.voxel.fog;
|
|
||||||
speIndex[0].constantID = 0;
|
|
||||||
speIndex[0].offset = offsetof(SpeData, fog);
|
|
||||||
speIndex[0].size = sizeof(SpeData::fog);
|
|
||||||
speData.pbr = options.voxel.pbr;
|
|
||||||
speIndex[1].constantID = 1;
|
|
||||||
speIndex[1].offset = offsetof(SpeData, pbr);
|
|
||||||
speIndex[1].size = sizeof(SpeData::pbr);
|
|
||||||
speData.triplanar = options.voxel.triplanar;
|
|
||||||
speIndex[2].constantID = 2;
|
|
||||||
speIndex[2].offset = offsetof(SpeData, triplanar);
|
|
||||||
speIndex[2].size = sizeof(SpeData::triplanar);
|
|
||||||
speData.stochastic = options.voxel.stochastic;
|
|
||||||
speIndex[3].constantID = 3;
|
|
||||||
speIndex[3].offset = offsetof(SpeData, stochastic);
|
|
||||||
speIndex[3].size = sizeof(SpeData::stochastic);
|
|
||||||
speData.blend = options.voxel.blend;
|
|
||||||
speIndex[4].constantID = 4;
|
|
||||||
speIndex[4].offset = offsetof(SpeData, blend);
|
|
||||||
speIndex[4].size = sizeof(SpeData::blend);
|
|
||||||
speData.curvature = options.voxel.curvature;
|
|
||||||
speIndex[5].constantID = 5;
|
|
||||||
speIndex[5].offset = offsetof(SpeData, curvature);
|
|
||||||
speIndex[5].size = sizeof(SpeData::curvature);
|
|
||||||
speData.curv_depth = options.voxel.curv_depth;
|
|
||||||
speIndex[6].constantID = 6;
|
|
||||||
speIndex[6].offset = offsetof(SpeData, curv_depth);
|
|
||||||
speIndex[6].size = sizeof(SpeData::curv_depth);
|
|
||||||
speData.unitSize = 8; //TODO: load from world.voxel_density
|
|
||||||
speIndex[7].constantID = 16;
|
|
||||||
speIndex[7].offset = offsetof(SpeData, unitSize);
|
|
||||||
speIndex[7].size = sizeof(SpeData::unitSize);
|
|
||||||
VkSpecializationInfo specialization{};
|
|
||||||
specialization.dataSize = sizeof(SpeData);
|
|
||||||
specialization.pData = &speData;
|
|
||||||
specialization.mapEntryCount = speIndex.size();
|
|
||||||
specialization.pMapEntries = speIndex.data();
|
|
||||||
|
|
||||||
auto withGeometry = options.voxel.geometry && info.features.geometryShader;
|
auto withGeometry = options.voxel.geometry && info.features.geometryShader;
|
||||||
auto shaderStages = setShaders(transparentWorldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &specialization);
|
auto shaderStages = setShaders(transparentWorldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &voxelSpecialization);
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
|
Loading…
Reference in New Issue