mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-22 19:19:52 +02:00
feat: more advanced armor highlighting
This commit is contained in:
1 parent
909474d4cb
commit
d469f990f6
10 files changed
+119
-199
No files matched your search
@@ -1,69 +1,58 @@
|
||||
import { MeshProps } from '@react-three/fiber';
|
||||
import { MeshStandardMaterial } from 'three';
|
||||
import CustomShaderMaterial from 'three-custom-shader-material';
|
||||
import fragment from './shaders/fragment.glsl';
|
||||
import vertex from './shaders/vertex.glsl';
|
||||
import fragmentShader from './shaders/fragment.glsl';
|
||||
|
||||
interface ArmorMeshProps extends MeshProps {
|
||||
isExplosive: boolean;
|
||||
canSplash: boolean;
|
||||
isSpaced: boolean;
|
||||
isArmor: boolean;
|
||||
thickness: number;
|
||||
penetration: number;
|
||||
caliber: number;
|
||||
spaced?: boolean;
|
||||
canRicochet: boolean;
|
||||
canSplash: boolean;
|
||||
ricochet?: number;
|
||||
normalization?: number;
|
||||
isAffectedBySpaced: boolean;
|
||||
ricochet: number;
|
||||
normalization: number;
|
||||
}
|
||||
|
||||
// shader split: https://github.com/FarazzShaikh/THREE-CustomShaderMaterial/issues/48
|
||||
|
||||
export function ArmorMesh({
|
||||
isExplosive,
|
||||
canSplash,
|
||||
isSpaced,
|
||||
isArmor,
|
||||
thickness,
|
||||
penetration,
|
||||
caliber,
|
||||
canRicochet,
|
||||
ricochet,
|
||||
canSplash,
|
||||
isAffectedBySpaced,
|
||||
normalization,
|
||||
spaced = false,
|
||||
...props
|
||||
}: ArmorMeshProps) {
|
||||
return (
|
||||
<>
|
||||
{!spaced && (
|
||||
{!isSpaced && (
|
||||
<mesh {...props}>
|
||||
<meshBasicMaterial colorWrite={false} />
|
||||
</mesh>
|
||||
)}
|
||||
|
||||
<mesh {...props} renderOrder={spaced ? 3 : 1}>
|
||||
<mesh {...props} renderOrder={1}>
|
||||
<CustomShaderMaterial
|
||||
silent
|
||||
baseMaterial={MeshStandardMaterial}
|
||||
transparent
|
||||
silent
|
||||
depthWrite={false}
|
||||
fragmentShader={fragmentShader}
|
||||
uniforms={{
|
||||
isExplosive: { value: isExplosive },
|
||||
canSplash: { value: canSplash },
|
||||
isSpaced: { value: isSpaced },
|
||||
isArmor: { value: isArmor },
|
||||
thickness: { value: thickness },
|
||||
penetration: { value: penetration },
|
||||
ricochet: {
|
||||
value: ricochet === undefined ? 0 : ricochet * (Math.PI / 180),
|
||||
},
|
||||
normalization: {
|
||||
value:
|
||||
normalization === undefined
|
||||
? 0
|
||||
: normalization * (Math.PI / 180),
|
||||
},
|
||||
caliber: { value: caliber },
|
||||
spaced: { value: spaced ?? false },
|
||||
canRicochet: { value: canRicochet },
|
||||
canSplash: { value: canSplash },
|
||||
isAffectedBySpaced: { value: isAffectedBySpaced },
|
||||
ricochet: { value: ricochet * (Math.PI / 180) },
|
||||
normalization: { value: normalization * (Math.PI / 180) },
|
||||
}}
|
||||
vertexShader={vertex}
|
||||
fragmentShader={fragment}
|
||||
/>
|
||||
</mesh>
|
||||
</>
|
||||
|
||||
@@ -1,75 +1,64 @@
|
||||
// split shaders due to https://github.com/FarazzShaikh/THREE-CustomShaderMaterial/issues/48
|
||||
|
||||
varying vec3 vCSMViewPosition;
|
||||
uniform bool isExplosive;
|
||||
uniform bool canSplash;
|
||||
uniform bool isSpaced;
|
||||
uniform bool isArmor;
|
||||
uniform float thickness;
|
||||
uniform float penetration;
|
||||
uniform float ricochet;
|
||||
uniform float caliber;
|
||||
uniform float ricochet;
|
||||
uniform float normalization;
|
||||
uniform bool spaced;
|
||||
uniform bool canRichochet;
|
||||
uniform bool canSplash;
|
||||
uniform bool isAffectedBySpaced;
|
||||
|
||||
vec3 zPositive = vec3(0.0, 0.0, 1.0);
|
||||
|
||||
void main() {
|
||||
vec3 normalizedNormal = normalize(vNormal);
|
||||
vec3 normalizedViewPosition = normalize(vCSMViewPosition);
|
||||
float dotProduct = dot(normalizedNormal, -normalizedViewPosition);
|
||||
float angle = acos(dotProduct);
|
||||
float cosAngle = dot(zPositive, vNormal);
|
||||
float angle = acos(cosAngle);
|
||||
|
||||
float penetrationChance = -1.0;
|
||||
bool threeCaliberRule = caliber > 3.0 * thickness;
|
||||
float splashChance = -1.0;
|
||||
bool threeCalibersRule = caliber > 3.0 * thickness;
|
||||
|
||||
if (canRichochet && !threeCaliberRule && angle >= ricochet) {
|
||||
// auto ricochet angle and three caliber rule not met
|
||||
if (isArmor && !isExplosive && !threeCalibersRule && angle >= ricochet) {
|
||||
penetrationChance = 0.0;
|
||||
splashChance = 0.0;
|
||||
} else {
|
||||
bool twoCaliberRule = caliber > 2.0 * thickness;
|
||||
float finalNormalization = twoCaliberRule ? (normalization * 1.4 * caliber) / (2.0 * thickness) : normalization;
|
||||
float effectiveArmor = thickness / cos(angle - finalNormalization);
|
||||
float penetrationRandomRadius = penetration * 0.05;
|
||||
float penetrationDifference = effectiveArmor - penetration;
|
||||
bool twoCalibersRule = caliber > 2.0 * thickness;
|
||||
float finalNormalization = twoCalibersRule ? (normalization * 1.4 * caliber) / (2.0 * thickness) : normalization;
|
||||
float finalThickness = thickness / cos(angle - finalNormalization);
|
||||
|
||||
if (penetrationDifference > penetrationRandomRadius) {
|
||||
// even with a +5% buff, can't penetrate
|
||||
penetrationChance = 0.0;
|
||||
} else if (penetrationDifference < -penetrationRandomRadius) {
|
||||
// event with a -5% nerf, can penetrate
|
||||
penetrationChance = 1.0;
|
||||
if (canSplash) {
|
||||
if (finalThickness * (5.0 / 11.0) > penetration) {
|
||||
penetrationChance = 0.0;
|
||||
splashChance = 0.0;
|
||||
} else if (finalThickness > penetration) {
|
||||
penetrationChance = 0.0;
|
||||
splashChance = 1.0;
|
||||
} else {
|
||||
penetrationChance = 1.0;
|
||||
splashChance = 1.0;
|
||||
}
|
||||
} else {
|
||||
// penetration gradiant
|
||||
penetrationChance = 1.0 - (penetrationDifference + penetrationRandomRadius) / (2.0 * penetrationRandomRadius);
|
||||
if (finalThickness > penetration) {
|
||||
penetrationChance = 0.0;
|
||||
splashChance = 0.0;
|
||||
} else {
|
||||
penetrationChance = 1.0;
|
||||
splashChance = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float alpha = (1.0 - penetrationChance) * 0.5;
|
||||
|
||||
if (canSplash) {
|
||||
// he
|
||||
if (spaced) {
|
||||
csm_FragColor = vec4(1.0, 0.0, 1.0, 0.5);
|
||||
} else {
|
||||
float angledThickness = thickness / cos(angle);
|
||||
|
||||
if (angledThickness * (5.0 / 11.0) > penetration) {
|
||||
csm_FragColor = vec4(1.0, 0.0, 0.0, alpha);
|
||||
} else {
|
||||
csm_FragColor = vec4(1.0, 0.392, 0.0, alpha);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (spaced) {
|
||||
if (isAffectedBySpaced) {
|
||||
// hc
|
||||
if (isSpaced) {
|
||||
if (isArmor) {
|
||||
if (isExplosive) {
|
||||
csm_FragColor = vec4(1.0, 0.0, 1.0, 0.5);
|
||||
} else {
|
||||
// ap, ap_cr
|
||||
csm_FragColor = vec4(1.0, 0.0, 1.0, alpha);
|
||||
csm_FragColor = vec4(1.0, 0.0, 1.0, (1.0 - penetrationChance) * 0.5);
|
||||
}
|
||||
} else {
|
||||
// ap, ap_cr, hc
|
||||
csm_FragColor = vec4(1.0, 0.0, 0.0, alpha);
|
||||
csm_FragColor = vec4(0.5, 0.0, 1.0, 0.5);
|
||||
}
|
||||
} else {
|
||||
csm_FragColor = vec4(1.0, splashChance * 0.392, 0.0, (1.0 - penetrationChance) * 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
varying vec3 vCSMViewPosition;
|
||||
|
||||
void main() {
|
||||
vec4 vViewPosition4 = modelViewMatrix * vec4(position, 1.0);
|
||||
vCSMViewPosition = vViewPosition4.xyz;
|
||||
}
|
||||
Reference in new issue
Block a user