diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java index de256a9a4..d4f3085f2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java @@ -46,7 +46,8 @@ public class ShaderLoader { // #flwinclude <"valid_namespace:valid/path_to_file.glsl"> private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); - private static boolean debugDumpFile = false; + private static final Pattern builtinPattern = Pattern.compile("#flwbuiltins"); + private static boolean debugDumpFile = true; final Map shaderSource = new HashMap<>(); @@ -64,6 +65,9 @@ public class ShaderLoader { Backend.registry.values().forEach(this::loadProgramFromSpec); Backend.log.info("Loaded all shader programs."); + + // no need to hog all that memory + shaderSource.clear(); } } } @@ -125,7 +129,54 @@ public class ShaderLoader { } } - private String processIncludes(ResourceLocation baseName, String source) { + public GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) { + String source = shaderSource.get(name); + + source = expandBuiltins(source, type); + source = processIncludes(source, name); + + if (defines != null) + source = defines.process(source); + + if (debugDumpFile) { + Backend.log.debug("Finished processing '" + name + "':"); + int i = 1; + for (String s : source.split("\n")) { + Backend.log.debug(String.format("%1$4s: ", i++) + s); + } + } + + return new GlShader(type, name, source); + } + + private String expandBuiltins(String source, ShaderType type) { + return lines(source).flatMap(line -> { + Matcher matcher = builtinPattern.matcher(line); + + if (matcher.find()) { + ResourceLocation builtins; + + switch (type) { + case FRAGMENT: + builtins = new ResourceLocation("create", "std/builtin.frag"); + break; + case VERTEX: + builtins = new ResourceLocation("create", "std/builtin.vert"); + break; + default: + builtins = null; + } + + String includeSource = shaderSource.get(builtins); + + return lines(includeSource); + } + + return Stream.of(line); + }).collect(Collectors.joining("\n")); + } + + private String processIncludes(String source, ResourceLocation baseName) { HashSet seen = new HashSet<>(); seen.add(baseName); @@ -133,7 +184,7 @@ public class ShaderLoader { } private Stream includeRecursive(String source, Set seen) { - return new BufferedReader(new StringReader(source)).lines().flatMap(line -> { + return lines(source).flatMap(line -> { Matcher matcher = includePattern.matcher(line); @@ -155,23 +206,8 @@ public class ShaderLoader { }); } - public GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) { - String source = shaderSource.get(name); - - source = processIncludes(name, source); - - if (defines != null) - source = defines.process(source); - - if (debugDumpFile) { - Backend.log.debug("Finished processing '" + name + "':"); - int i = 1; - for (String s : source.split("\n")) { - Backend.log.debug(String.format("%1$4s: ", i++) + s); - } - } - - return new GlShader(type, name, source); + public static Stream lines(String s) { + return new BufferedReader(new StringReader(s)).lines(); } public String readToString(InputStream is) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index 89eabc9d0..cea898c4f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -105,13 +105,7 @@ public abstract class GlProgram extends GlObject { } /** - * Links the attached shaders to this program and returns a user-defined container which wraps the shader - * program. This container can, for example, provide methods for updating the specific uniforms of that shader - * set. - * - * @param factory The factory which will create the shader program's container - * @param

The type which should be instantiated with the new program's handle - * @return An instantiated shader container as provided by the factory + * Links the attached shaders to this program. */ public Builder link() { GL20.glLinkProgram(this.program); diff --git a/src/main/resources/assets/create/flywheel/shaders/belt.vert b/src/main/resources/assets/create/flywheel/shaders/belt.vert index 6edba4c07..78937f401 100644 --- a/src/main/resources/assets/create/flywheel/shaders/belt.vert +++ b/src/main/resources/assets/create/flywheel/shaders/belt.vert @@ -1,6 +1,7 @@ #version 110 #define PI 3.1415926538 +#flwbuiltins #flwinclude <"create:core/quaternion.glsl"> #flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/diffuse.glsl"> @@ -30,16 +31,6 @@ uniform int uDebug; uniform vec3 uCameraPos; -#if defined(USE_FOG) -varying float FragDistance; -#endif - -#ifdef CONTRAPTION -#flwinclude <"create:contraption/builtin.vert"> -#else -#flwinclude <"create:std/builtin.vert"> -#endif - void main() { vec3 rotated = rotateVertexByQuat(aPos - .5, aInstanceRot) + aInstancePos + .5; @@ -47,7 +38,7 @@ void main() { vec3 norm = rotateVertexByQuat(aNormal, aInstanceRot); - FLWFinalizeWorldPos(worldPos); + FLWFinalizeWorldPos(worldPos, uCameraPos); FLWFinalizeNormal(norm); float scrollSize = aScrollTexture.w - aScrollTexture.y; diff --git a/src/main/resources/assets/create/flywheel/shaders/block.frag b/src/main/resources/assets/create/flywheel/shaders/block.frag index 0ad89defe..ccac8b02b 100644 --- a/src/main/resources/assets/create/flywheel/shaders/block.frag +++ b/src/main/resources/assets/create/flywheel/shaders/block.frag @@ -1,5 +1,7 @@ #version 110 +#flwbuiltins + varying vec2 TexCoords; varying vec2 Light; varying float Diffuse; @@ -8,45 +10,12 @@ varying vec4 Color; uniform sampler2D uBlockAtlas; uniform sampler2D uLightMap; -#if defined(USE_FOG) -varying float FragDistance; -uniform vec4 uFogColor; -#endif - -#if defined(USE_FOG_LINEAR) -uniform vec2 uFogRange; - -float fogFactor() { - return (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x); -} -#endif - -#ifdef USE_FOG_EXP2 -uniform float uFogDensity; - -float fogFactor() { - float dist = FragDistance * uFogDensity; - return 1. / exp2(dist * dist); -} - #endif - - #ifdef CONTRAPTION - #flwinclude <"create:contraption/builtin.frag"> - #else - #flwinclude <"create:std/builtin.frag"> - #endif - void main() { vec4 tex = texture2D(uBlockAtlas, TexCoords); vec4 color = vec4(tex.rgb * FLWLight(Light, uLightMap).rgb * Diffuse, tex.a) * Color; - #if defined(USE_FOG) - float fog = clamp(fogFactor(), 0., 1.); + FLWFinalizeColor(color); - gl_FragColor = mix(uFogColor, color, fog); - gl_FragColor.a = color.a; -#else gl_FragColor = color; -#endif } diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.frag b/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.frag index eb9014677..f1562aad4 100644 --- a/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.frag +++ b/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.frag @@ -1,6 +1,16 @@ varying vec3 BoxCoord; uniform sampler3D uLightVolume; +void FLWFinalizeColor(vec4 color) { + #if defined(USE_FOG) + float a = color.a; + float fog = clamp(FLWFogFactor(), 0., 1.); + + color = mix(uFogColor, color, fog); + color.a = a; + #endif +} + vec4 FLWLight(vec2 lightCoords, sampler2D lightMap) { vec2 lm = max(lightCoords, texture3D(uLightVolume, BoxCoord).rg); return texture2D(lightMap, lm * 0.9375 + 0.03125); diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.vert b/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.vert index ed55cc3a9..63aafdbda 100644 --- a/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.vert +++ b/src/main/resources/assets/create/flywheel/shaders/contraption/builtin.vert @@ -1,20 +1,28 @@ +#if defined(USE_FOG) +varying float FragDistance; +#endif + varying vec3 BoxCoord; uniform vec3 uLightBoxSize; uniform vec3 uLightBoxMin; uniform mat4 uModel; -void FLWFinalizeWorldPos(inout vec4 worldPos) { +void FLWFinalizeWorldPos(inout vec4 worldPos, vec3 cameraPos) { worldPos = uModel * worldPos; BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - #if defined(USE_FOG) + #if defined(USE_FOG) FragDistance = length(worldPos.xyz); #endif } void FLWFinalizeNormal(inout vec3 normal) { - normal = modelToNormal(uModel) * normal; + mat3 m; + m[0] = uModel[0].xyz; + m[1] = uModel[1].xyz; + m[2] = uModel[2].xyz; + normal = m * normal; } diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert index b58a4df0e..4de728759 100644 --- a/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert +++ b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert @@ -19,7 +19,6 @@ attribute vec4 aInstanceRot; attribute vec3 aRotationCenter; attribute float aSpeed; - varying float Diffuse; varying vec2 TexCoords; varying vec4 Color; @@ -68,4 +67,4 @@ void main() { } else { Color = vec4(1.); } -} \ No newline at end of file +} diff --git a/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl b/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl index f7c846e71..d5f4d9c6c 100644 --- a/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl +++ b/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl @@ -1,17 +1,4 @@ -//mat4 rotate(vec3 axis, float angle) { -// float s = sin(angle); -// float c = cos(angle); -// float oc = 1. - c; -// -// return mat4( -// oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0., -// oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0., -// oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0., -// 0., 0., 0., 1. -// ); -//} - mat4 rotate(vec3 axis, float angle) { float s = sin(angle); float c = cos(angle); @@ -39,4 +26,4 @@ mat3 modelToNormal(mat4 mat) { m[1] = mat[1].xyz; m[2] = mat[2].xyz; return m; -} \ No newline at end of file +} diff --git a/src/main/resources/assets/create/flywheel/shaders/flap.vert b/src/main/resources/assets/create/flywheel/shaders/flap.vert index 037c603c2..8b79964c1 100644 --- a/src/main/resources/assets/create/flywheel/shaders/flap.vert +++ b/src/main/resources/assets/create/flywheel/shaders/flap.vert @@ -1,6 +1,7 @@ #version 110 #define PI 3.1415926538 +#flwbuiltins #flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/quaternion.glsl"> #flwinclude <"create:core/diffuse.glsl"> @@ -32,16 +33,6 @@ uniform int uDebug; uniform vec3 uCameraPos; -#if defined(USE_FOG) -varying float FragDistance; -#endif - -#ifdef CONTRAPTION -#flwinclude <"create:contraption/builtin.vert"> -#else -#flwinclude <"create:std/builtin.vert"> -#endif - float toRad(float degrees) { return fract(degrees / 360.) * PI * 2.; } @@ -71,7 +62,7 @@ void main() { vec4 worldPos = vec4(rotated, 1.); vec3 norm = rotateVertexByQuat(rotateVertexByQuat(aNormal, flapRotation), orientation); - FLWFinalizeWorldPos(worldPos); + FLWFinalizeWorldPos(worldPos, uCameraPos); FLWFinalizeNormal(norm); Diffuse = diffuse(norm); diff --git a/src/main/resources/assets/create/flywheel/shaders/model.vert b/src/main/resources/assets/create/flywheel/shaders/model.vert index e0a62efe7..a6c5e3ec1 100644 --- a/src/main/resources/assets/create/flywheel/shaders/model.vert +++ b/src/main/resources/assets/create/flywheel/shaders/model.vert @@ -1,5 +1,6 @@ #version 110 +#flwbuiltins #flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/diffuse.glsl"> @@ -23,24 +24,13 @@ uniform int uDebug; uniform vec3 uCameraPos; -#if defined(USE_FOG) -varying float FragDistance; -#endif - -#ifdef CONTRAPTION -#flwinclude <"create:contraption/builtin.vert"> -#else -#flwinclude <"create:std/builtin.vert"> -#endif - - void main() { vec4 worldPos = aTransform * vec4(aPos, 1.); vec3 norm = aNormalMat * aNormal; + FLWFinalizeWorldPos(worldPos, uCameraPos); FLWFinalizeNormal(norm); - FLWFinalizeWorldPos(worldPos); norm = normalize(norm); diff --git a/src/main/resources/assets/create/flywheel/shaders/oriented.vert b/src/main/resources/assets/create/flywheel/shaders/oriented.vert index e88371820..8c94ecd04 100644 --- a/src/main/resources/assets/create/flywheel/shaders/oriented.vert +++ b/src/main/resources/assets/create/flywheel/shaders/oriented.vert @@ -1,5 +1,6 @@ #version 110 +#flwbuiltins #flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/quaternion.glsl"> #flwinclude <"create:core/diffuse.glsl"> @@ -25,22 +26,12 @@ uniform int uDebug; uniform vec3 uCameraPos; -#if defined(USE_FOG) -varying float FragDistance; -#endif - -#ifdef CONTRAPTION -#flwinclude <"create:contraption/builtin.vert"> -#else -#flwinclude <"create:std/builtin.vert"> -#endif - void main() { vec4 worldPos = vec4(rotateVertexByQuat(aPos - aPivot, aRotation) + aPivot + aInstancePos, 1.); vec3 norm = rotateVertexByQuat(aNormal, aRotation); - FLWFinalizeWorldPos(worldPos); + FLWFinalizeWorldPos(worldPos, uCameraPos); FLWFinalizeNormal(norm); Diffuse = diffuse(norm); diff --git a/src/main/resources/assets/create/flywheel/shaders/rotating.vert b/src/main/resources/assets/create/flywheel/shaders/rotating.vert index d2eaeb63b..770ef4ccc 100644 --- a/src/main/resources/assets/create/flywheel/shaders/rotating.vert +++ b/src/main/resources/assets/create/flywheel/shaders/rotating.vert @@ -1,6 +1,7 @@ #version 110 #define PI 3.1415926538 +#flwbuiltins #flwinclude <"create:core/quaternion.glsl"> #flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/diffuse.glsl"> @@ -27,16 +28,6 @@ uniform int uDebug; uniform vec3 uCameraPos; -#if defined(USE_FOG) -varying float FragDistance; -#endif - -#ifdef CONTRAPTION -#flwinclude <"create:contraption/builtin.vert"> -#else -#flwinclude <"create:std/builtin.vert"> -#endif - mat4 kineticRotation() { float degrees = aOffset + uTime * aSpeed * 3./10.; float angle = fract(degrees / 360.) * PI * 2.; @@ -50,7 +41,7 @@ void main() { vec3 norm = modelToNormal(kineticRotation) * aNormal; - FLWFinalizeWorldPos(worldPos); + FLWFinalizeWorldPos(worldPos, uCameraPos); FLWFinalizeNormal(norm); Diffuse = diffuse(norm); diff --git a/src/main/resources/assets/create/flywheel/shaders/std/builtin.frag b/src/main/resources/assets/create/flywheel/shaders/std/builtin.frag index d133154cf..347537366 100644 --- a/src/main/resources/assets/create/flywheel/shaders/std/builtin.frag +++ b/src/main/resources/assets/create/flywheel/shaders/std/builtin.frag @@ -1,4 +1,21 @@ +#flwinclude <"create:std/fog.glsl"> + +#if defined(CONTRAPTION) +#flwinclude <"create:contraption/builtin.frag"> +#else + +void FLWFinalizeColor(vec4 color) { + #if defined(USE_FOG) + float a = color.a; + float fog = clamp(FLWFogFactor(), 0., 1.); + + color = mix(uFogColor, color, fog); + color.a = a; + #endif +} + vec4 FLWLight(vec2 lightCoords, sampler2D lightMap) { vec2 lm = lightCoords * 0.9375 + 0.03125; return texture2D(lightMap, lm); } + #endif diff --git a/src/main/resources/assets/create/flywheel/shaders/std/builtin.vert b/src/main/resources/assets/create/flywheel/shaders/std/builtin.vert index e3f3180bf..5c542b77f 100644 --- a/src/main/resources/assets/create/flywheel/shaders/std/builtin.vert +++ b/src/main/resources/assets/create/flywheel/shaders/std/builtin.vert @@ -1,10 +1,18 @@ -void FLWFinalizeWorldPos(inout vec4 worldPos) { - #if defined(USE_FOG) +#if defined(CONTRAPTION) +#flwinclude <"create:contraption/builtin.vert"> +#else - FragDistance = length(worldPos.xyz - uCameraPos); +#if defined(USE_FOG) +varying float FragDistance; +#endif + +void FLWFinalizeWorldPos(inout vec4 worldPos, vec3 cameraPos) { + #if defined(USE_FOG) + FragDistance = length(worldPos.xyz - cameraPos); #endif } void FLWFinalizeNormal(inout vec3 normal) { // noop } + #endif diff --git a/src/main/resources/assets/create/flywheel/shaders/std/fog.glsl b/src/main/resources/assets/create/flywheel/shaders/std/fog.glsl new file mode 100644 index 000000000..09cc7af18 --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/std/fog.glsl @@ -0,0 +1,23 @@ +#if defined(USE_FOG) +varying float FragDistance; +uniform vec4 uFogColor; +#endif + +#if defined(USE_FOG_LINEAR) +uniform vec2 uFogRange; + +float FLWFogFactor() { + return (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x); +} + #elif defined(USE_FOG_EXP2) +uniform float uFogDensity; + +float FLWFogFactor() { + float dist = FragDistance * uFogDensity; + return 1. / exp2(dist * dist); +} + #else +float FLWFogFactor() { + return 0.; +} + #endif