From 318a71bd32d1ad3e077d0a2f1ee0bc979a42ecd2 Mon Sep 17 00:00:00 2001
From: tresabhi <43380238+tresabhi@users.noreply.github.com>
Date: Sun, 15 Dec 2024 18:13:23 -0600
Subject: [PATCH] feat: advanced mode
---
.../PrimaryArmorSceneComponent/index.tsx | 19 ++-
.../shaders/fragment.glsl | 20 +++-
.../HeroSection/components/Options/index.tsx | 108 +++++++++++-------
.../TankSandbox/components/Control.tsx | 1 -
.../src/stores/tankopediaPersistent/index.ts | 2 +
5 files changed, 98 insertions(+), 52 deletions(-)
diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx
index 519646c10..462288558 100644
--- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx
+++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx
@@ -49,6 +49,7 @@ export function PrimaryArmorSceneComponent({
damage: { value: null },
explosionRadius: { value: null },
greenPenetration: { value: null },
+ advancedHighlighting: { value: null },
opaque: { value: null },
inverseProjectionMatrix: { value: null },
@@ -90,6 +91,9 @@ export function PrimaryArmorSceneComponent({
function handleGreenPenetrationChange(greenPenetration: boolean) {
material.uniforms.greenPenetration.value = greenPenetration;
}
+ function handleAdvancedHighlightingChange(advancedHighlighting: boolean) {
+ material.uniforms.advancedHighlighting.value = advancedHighlighting;
+ }
function handleOpaqueChange(opaque: boolean) {
material.uniforms.opaque.value = opaque;
}
@@ -133,12 +137,13 @@ export function PrimaryArmorSceneComponent({
if (!noInvalidate) invalidate();
}
+ const initialState = tankopediaPersistentStore.getState();
+
handleShellChange();
- handleGreenPenetrationChange(
- tankopediaPersistentStore.getState().greenPenetration,
- );
- handleOpaqueChange(tankopediaPersistentStore.getState().opaque);
- handleWireframeChange(tankopediaPersistentStore.getState().wireframe);
+ handleGreenPenetrationChange(initialState.greenPenetration);
+ handleAdvancedHighlightingChange(initialState.advancedHighlighting);
+ handleOpaqueChange(initialState.opaque);
+ handleWireframeChange(initialState.wireframe);
handleProtagonistEquipmentChange(
duelStore.getState().protagonist.equipmentMatrix,
);
@@ -156,6 +161,10 @@ export function PrimaryArmorSceneComponent({
(state) => state.greenPenetration,
handleGreenPenetrationChange,
),
+ tankopediaPersistentStore.subscribe(
+ (state) => state.advancedHighlighting,
+ handleAdvancedHighlightingChange,
+ ),
tankopediaPersistentStore.subscribe(
(state) => state.opaque,
handleOpaqueChange,
diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl
index 045d49a80..76bc4520f 100644
--- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl
+++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl
@@ -12,6 +12,7 @@ uniform bool canSplash;
uniform float damage;
uniform float explosionRadius;
uniform bool greenPenetration;
+uniform bool advancedHighlighting;
uniform bool opaque;
uniform mat4 inverseProjectionMatrix;
@@ -27,16 +28,18 @@ float depthToDistance(float depth) {
void main() {
float penetrationChance = -1.0;
float splashChance = -1.0;
+ bool didRicochet = false;
vec2 screenCoordinates = gl_FragCoord.xy / resolution;
float angle = acos(dot(vNormal, -vViewPosition) / length(vViewPosition));
vec4 spacedArmorBufferFragment = texture2D(spacedArmorBuffer, screenCoordinates);
bool isUnderSpacedArmor = spacedArmorBufferFragment.a != 0.0;
-
bool threeCalibersRule = caliber > thickness * 3.0 || isUnderSpacedArmor;
+
if (!threeCalibersRule && angle >= ricochet) {
penetrationChance = 0.0;
+ didRicochet = true;
} else {
bool twoCalibersRule = caliber > thickness * 2.0 && thickness > 0.0;
float finalNormalization = twoCalibersRule ? ((1.4 * normalization * caliber) / (2.0 * thickness)) : normalization;
@@ -82,11 +85,22 @@ void main() {
float alpha = opaque ? 1.0 : 0.5;
vec3 color = vec3(1.0, splashChance * 0.392, 0.0);
- if (greenPenetration) {
+
+ if (advancedHighlighting && didRicochet) {
+ color = vec3(1.0, color.g, 1.0);
+ }
+
+ if (greenPenetration || advancedHighlighting) {
// non-trigonometric red-green mixing: https://www.desmos.com/calculator/ceo1oq7l67
float falling = -pow(penetrationChance, 2.0) + 1.0;
float gaining = -pow(penetrationChance - 1.0, 2.0) + 1.0;
- gl_FragColor = vec4(falling * color + gaining * vec3(0.0, 1.0, 0.0), alpha);
+ vec3 penetrationColor = vec3(0.0, 1.0, 0.0);
+
+ if (advancedHighlighting && threeCalibersRule) {
+ penetrationColor = vec3(0.0, 1.0, 1.0);
+ }
+
+ gl_FragColor = vec4(falling * color + gaining * penetrationColor, alpha);
} else {
gl_FragColor = vec4(color, (1.0 - penetrationChance) * alpha);
}
diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx
index 20dad8563..1e4baa024 100644
--- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx
+++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx
@@ -17,6 +17,7 @@ import {
import {
Box,
Button,
+ Checkbox,
Dialog,
DropdownMenu,
Flex,
@@ -68,6 +69,9 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
const greenPenetration = TankopediaPersistent.use(
(state) => state.greenPenetration,
);
+ const advancedHighlighting = TankopediaPersistent.use(
+ (state) => state.advancedHighlighting,
+ );
const wireframe = TankopediaPersistent.use((state) => state.wireframe);
const opaque = TankopediaPersistent.use((state) => state.opaque);
const fullScreenAvailable = useFullscreenAvailability();
@@ -325,53 +329,71 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
style={{ transform: 'translateX(-50%)' }}
>
{display === TankopediaDisplay.DynamicArmor && (
-
-
- Shooter:
-
-
+ {
+ mutateTankopediaPersistent((draft) => {
+ draft.advancedHighlighting = !draft.advancedHighlighting;
+ });
+ }}
>
-
-
-
+
+
+ Advanced highlighting
+
+
-
- Select tank
+
+
+ Shooter:
+
+
+
+
+
-
- {
- mutateDuel((draft) => {
- draft.antagonist.tank = tank;
- draft.antagonist.engine = tank.engines.at(-1)!;
- draft.antagonist.track = tank.tracks.at(-1)!;
- draft.antagonist.turret = tank.turrets.at(-1)!;
- draft.antagonist.gun =
- draft.antagonist.turret.guns.at(-1)!;
- draft.antagonist.shell =
- draft.antagonist.gun.gun_type!.value.base.shells[0];
- });
- setAntagonistSelectorOpen(false);
- }}
- />
-
-
-
-
+
+ Select tank
+
+
+ {
+ mutateDuel((draft) => {
+ draft.antagonist.tank = tank;
+ draft.antagonist.engine = tank.engines.at(-1)!;
+ draft.antagonist.track = tank.tracks.at(-1)!;
+ draft.antagonist.turret = tank.turrets.at(-1)!;
+ draft.antagonist.gun =
+ draft.antagonist.turret.guns.at(-1)!;
+ draft.antagonist.shell =
+ draft.antagonist.gun.gun_type!.value.base.shells[0];
+ });
+ setAntagonistSelectorOpen(false);
+ }}
+ />
+
+
+
+
+ >
)}
-
diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts
index c70dd4607..d8054b75a 100644
--- a/packages/website/src/stores/tankopediaPersistent/index.ts
+++ b/packages/website/src/stores/tankopediaPersistent/index.ts
@@ -12,6 +12,7 @@ export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';
export interface TankopediaPersistentStore {
wireframe: boolean;
opaque: boolean;
+ advancedHighlighting: boolean;
environment: (typeof ENVIRONMENTS)[number];
showGrid: boolean;
greenPenetration: boolean;
@@ -33,6 +34,7 @@ export const TankopediaPersistent = createContextualStore(() =>
subscribeWithSelector(() => ({
wireframe: false,
opaque: false,
+ advancedHighlighting: false,
environment: ENVIRONMENTS[0],
showGrid: true,
greenPenetration: false,