Relativistic crumbling

- Apply crumbling texture based on model space coordinates, not world
  space.
- Discard based both on crumbling alpha and diffuse alpha.
This commit is contained in:
Jozufozu 2023-11-26 19:24:04 -08:00
parent 24aa5b1795
commit be74a5a21b
8 changed files with 89 additions and 40 deletions

View File

@ -94,11 +94,24 @@ public class InstancingEngine extends AbstractEngine {
}
try (var state = GlStateTracker.getRestoreState()) {
ModelBakery.DESTROY_TYPES.get(progress)
.setupRenderState();
var crumblingType = ModelBakery.DESTROY_TYPES.get(progress);
for (var entry : drawMap.entrySet()) {
setup(entry.getKey(), Contexts.CRUMBLING);
var shader = entry.getKey();
setup(shader, Contexts.CRUMBLING);
shader.material().setup();
int renderTex = RenderSystem.getShaderTexture(0);
shader.material().clear();
crumblingType.setupRenderState();
RenderSystem.setShaderTexture(1, renderTex);
GlTextureUnit.T1.makeActive();
RenderSystem.bindTexture(renderTex);
for (Runnable draw : entry.getValue()) {
draw.run();

View File

@ -17,10 +17,10 @@ public final class Contexts {
GlProgram.unbind();
}));
// TODO: can we make crumbling a fragment material?
public static final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT, program -> {
public static final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.CRUMBLING_VERTEX, Files.CRUMBLING_FRAGMENT, program -> {
program.bind();
program.setSamplerBinding("flw_diffuseTex", 0);
program.setSamplerBinding("flw_crumblingTex", 0);
program.setSamplerBinding("flw_diffuseTex", 1);
GlProgram.unbind();
}));

View File

@ -1,8 +0,0 @@
#include "flywheel:api/vertex.glsl"
#include "flywheel:util/fog.glsl"
void flw_contextVertex() {
flw_distance = fog_distance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
gl_Position = flywheel.viewProjection * flw_vertexPos;
flw_vertexNormal = normalize(flw_vertexNormal);
}

View File

@ -1,32 +1,27 @@
#include "flywheel:api/fragment.glsl"
// optimize discard usage
#ifdef ALPHA_DISCARD
#ifdef GL_ARB_conservative_depth
layout (depth_greater) out float gl_FragDepth;
#endif
#endif
uniform sampler2D flw_diffuseTex;
uniform sampler2D flw_crumblingTex;
in vec2 flw_crumblingTexCoord;
out vec4 fragColor;
vec2 flattenedPos(vec3 pos, vec3 normal) {
pos -= floor(pos) + vec3(0.5);
float sinYRot = -normal.x;
vec2 XZ = normal.xz;
float sqLength = dot(XZ, XZ);
if (sqLength > 0) {
sinYRot *= inversesqrt(sqLength);
sinYRot = clamp(sinYRot, -1, 1);
}
vec3 tangent = vec3(sqrt(1 - sinYRot * sinYRot) * (normal.z < 0 ? -1 : 1), 0, sinYRot);
vec3 bitangent = cross(tangent, normal);
mat3 tbn = mat3(tangent, bitangent, normal);
// transpose is the same as inverse for orthonormal matrices
return (transpose(tbn) * pos).xy + vec2(0.5);
}
vec4 flw_crumblingSampleColor;
void flw_initFragment() {
flw_sampleColor = texture(flw_diffuseTex, flattenedPos(flw_vertexPos.xyz, flw_vertexNormal));
// Crumbling ignores vertex colors
flw_fragColor = flw_sampleColor;
flw_crumblingSampleColor = texture(flw_crumblingTex, flw_crumblingTexCoord);
flw_sampleColor = texture(flw_diffuseTex, flw_vertexTexCoord);
// Let the other components modify the diffuse color as they normally would.
flw_fragColor = flw_vertexColor * flw_sampleColor;
flw_fragOverlay = flw_vertexOverlay;
flw_fragLight = flw_vertexLight;
}
@ -34,10 +29,10 @@ void flw_initFragment() {
void flw_contextFragment() {
vec4 color = flw_fragColor;
// Ignore the discard predicate since we control the texture.
if (color.a < 0.01) {
// Still need to discard based on the diffuse color so we don't crumble over empty space.
if (flw_discardPredicate(color) || flw_crumblingSampleColor.a < 0.01) {
discard;
}
fragColor = flw_fogFilter(color);
fragColor = flw_fogFilter(flw_crumblingSampleColor);
}

View File

@ -1 +1,37 @@
#include "flywheel:context/common.vert"
#include "flywheel:api/vertex.glsl"
#include "flywheel:util/fog.glsl"
out vec2 flw_crumblingTexCoord;
vec3 tangent(vec3 normal) {
float sinYRot = -normal.x;
vec2 XZ = normal.xz;
float sqLength = dot(XZ, XZ);
if (sqLength > 0) {
sinYRot *= inversesqrt(sqLength);
sinYRot = clamp(sinYRot, -1, 1);
}
return vec3(sqrt(1 - sinYRot * sinYRot) * (normal.z < 0 ? -1 : 1), 0, sinYRot);
}
vec2 flattenedPos(vec3 pos, vec3 normal) {
pos -= vec3(0.5);
vec3 tangent = tangent(normal);
vec3 bitangent = cross(tangent, normal);
mat3 tbn = mat3(tangent, bitangent, normal);
// transpose is the same as inverse for orthonormal matrices
return (transpose(tbn) * pos).xy + vec2(0.5);
}
void flw_initVertex() {
flw_crumblingTexCoord = flattenedPos(flw_vertexPos.xyz, flw_vertexNormal);
}
void flw_contextVertex() {
flw_distance = fog_distance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
gl_Position = flywheel.viewProjection * flw_vertexPos;
flw_vertexNormal = normalize(flw_vertexNormal);
}

View File

@ -1 +1,12 @@
#include "flywheel:context/common.vert"
#include "flywheel:api/vertex.glsl"
#include "flywheel:util/fog.glsl"
void flw_initVertex() {
// noop
}
void flw_contextVertex() {
flw_distance = fog_distance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
gl_Position = flywheel.viewProjection * flw_vertexPos;
flw_vertexNormal = normalize(flw_vertexNormal);
}

View File

@ -26,6 +26,7 @@ void main() {
_flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID;
flw_layoutVertex();
flw_initVertex();
flw_instanceVertex(i);
flw_materialVertex();
flw_contextVertex();

View File

@ -9,6 +9,7 @@ void main() {
FlwInstance i = _flw_unpackInstance();
flw_layoutVertex();
flw_initVertex();
flw_instanceVertex(i);
flw_materialVertex();
flw_contextVertex();