mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: advanced mode
This commit is contained in:
1 parent
bc9c9ad4e7
commit
318a71bd32
5 files changed
+56
-10
No files matched your search
+14
-5
@@ -49,6 +49,7 @@ export function PrimaryArmorSceneComponent({
|
|||||||
damage: { value: null },
|
damage: { value: null },
|
||||||
explosionRadius: { value: null },
|
explosionRadius: { value: null },
|
||||||
greenPenetration: { value: null },
|
greenPenetration: { value: null },
|
||||||
|
advancedHighlighting: { value: null },
|
||||||
opaque: { value: null },
|
opaque: { value: null },
|
||||||
|
|
||||||
inverseProjectionMatrix: { value: null },
|
inverseProjectionMatrix: { value: null },
|
||||||
@@ -90,6 +91,9 @@ export function PrimaryArmorSceneComponent({
|
|||||||
function handleGreenPenetrationChange(greenPenetration: boolean) {
|
function handleGreenPenetrationChange(greenPenetration: boolean) {
|
||||||
material.uniforms.greenPenetration.value = greenPenetration;
|
material.uniforms.greenPenetration.value = greenPenetration;
|
||||||
}
|
}
|
||||||
|
function handleAdvancedHighlightingChange(advancedHighlighting: boolean) {
|
||||||
|
material.uniforms.advancedHighlighting.value = advancedHighlighting;
|
||||||
|
}
|
||||||
function handleOpaqueChange(opaque: boolean) {
|
function handleOpaqueChange(opaque: boolean) {
|
||||||
material.uniforms.opaque.value = opaque;
|
material.uniforms.opaque.value = opaque;
|
||||||
}
|
}
|
||||||
@@ -133,12 +137,13 @@ export function PrimaryArmorSceneComponent({
|
|||||||
if (!noInvalidate) invalidate();
|
if (!noInvalidate) invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initialState = tankopediaPersistentStore.getState();
|
||||||
|
|
||||||
handleShellChange();
|
handleShellChange();
|
||||||
handleGreenPenetrationChange(
|
handleGreenPenetrationChange(initialState.greenPenetration);
|
||||||
tankopediaPersistentStore.getState().greenPenetration,
|
handleAdvancedHighlightingChange(initialState.advancedHighlighting);
|
||||||
);
|
handleOpaqueChange(initialState.opaque);
|
||||||
handleOpaqueChange(tankopediaPersistentStore.getState().opaque);
|
handleWireframeChange(initialState.wireframe);
|
||||||
handleWireframeChange(tankopediaPersistentStore.getState().wireframe);
|
|
||||||
handleProtagonistEquipmentChange(
|
handleProtagonistEquipmentChange(
|
||||||
duelStore.getState().protagonist.equipmentMatrix,
|
duelStore.getState().protagonist.equipmentMatrix,
|
||||||
);
|
);
|
||||||
@@ -156,6 +161,10 @@ export function PrimaryArmorSceneComponent({
|
|||||||
(state) => state.greenPenetration,
|
(state) => state.greenPenetration,
|
||||||
handleGreenPenetrationChange,
|
handleGreenPenetrationChange,
|
||||||
),
|
),
|
||||||
|
tankopediaPersistentStore.subscribe(
|
||||||
|
(state) => state.advancedHighlighting,
|
||||||
|
handleAdvancedHighlightingChange,
|
||||||
|
),
|
||||||
tankopediaPersistentStore.subscribe(
|
tankopediaPersistentStore.subscribe(
|
||||||
(state) => state.opaque,
|
(state) => state.opaque,
|
||||||
handleOpaqueChange,
|
handleOpaqueChange,
|
||||||
|
|||||||
+17
-3
@@ -12,6 +12,7 @@ uniform bool canSplash;
|
|||||||
uniform float damage;
|
uniform float damage;
|
||||||
uniform float explosionRadius;
|
uniform float explosionRadius;
|
||||||
uniform bool greenPenetration;
|
uniform bool greenPenetration;
|
||||||
|
uniform bool advancedHighlighting;
|
||||||
uniform bool opaque;
|
uniform bool opaque;
|
||||||
uniform mat4 inverseProjectionMatrix;
|
uniform mat4 inverseProjectionMatrix;
|
||||||
|
|
||||||
@@ -27,16 +28,18 @@ float depthToDistance(float depth) {
|
|||||||
void main() {
|
void main() {
|
||||||
float penetrationChance = -1.0;
|
float penetrationChance = -1.0;
|
||||||
float splashChance = -1.0;
|
float splashChance = -1.0;
|
||||||
|
bool didRicochet = false;
|
||||||
|
|
||||||
vec2 screenCoordinates = gl_FragCoord.xy / resolution;
|
vec2 screenCoordinates = gl_FragCoord.xy / resolution;
|
||||||
float angle = acos(dot(vNormal, -vViewPosition) / length(vViewPosition));
|
float angle = acos(dot(vNormal, -vViewPosition) / length(vViewPosition));
|
||||||
|
|
||||||
vec4 spacedArmorBufferFragment = texture2D(spacedArmorBuffer, screenCoordinates);
|
vec4 spacedArmorBufferFragment = texture2D(spacedArmorBuffer, screenCoordinates);
|
||||||
bool isUnderSpacedArmor = spacedArmorBufferFragment.a != 0.0;
|
bool isUnderSpacedArmor = spacedArmorBufferFragment.a != 0.0;
|
||||||
|
|
||||||
bool threeCalibersRule = caliber > thickness * 3.0 || isUnderSpacedArmor;
|
bool threeCalibersRule = caliber > thickness * 3.0 || isUnderSpacedArmor;
|
||||||
|
|
||||||
if (!threeCalibersRule && angle >= ricochet) {
|
if (!threeCalibersRule && angle >= ricochet) {
|
||||||
penetrationChance = 0.0;
|
penetrationChance = 0.0;
|
||||||
|
didRicochet = true;
|
||||||
} else {
|
} else {
|
||||||
bool twoCalibersRule = caliber > thickness * 2.0 && thickness > 0.0;
|
bool twoCalibersRule = caliber > thickness * 2.0 && thickness > 0.0;
|
||||||
float finalNormalization = twoCalibersRule ? ((1.4 * normalization * caliber) / (2.0 * thickness)) : normalization;
|
float finalNormalization = twoCalibersRule ? ((1.4 * normalization * caliber) / (2.0 * thickness)) : normalization;
|
||||||
@@ -82,11 +85,22 @@ void main() {
|
|||||||
|
|
||||||
float alpha = opaque ? 1.0 : 0.5;
|
float alpha = opaque ? 1.0 : 0.5;
|
||||||
vec3 color = vec3(1.0, splashChance * 0.392, 0.0);
|
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
|
// non-trigonometric red-green mixing: https://www.desmos.com/calculator/ceo1oq7l67
|
||||||
float falling = -pow(penetrationChance, 2.0) + 1.0;
|
float falling = -pow(penetrationChance, 2.0) + 1.0;
|
||||||
float gaining = -pow(penetrationChance - 1.0, 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 {
|
} else {
|
||||||
gl_FragColor = vec4(color, (1.0 - penetrationChance) * alpha);
|
gl_FragColor = vec4(color, (1.0 - penetrationChance) * alpha);
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-1
@@ -17,6 +17,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
|
Checkbox,
|
||||||
Dialog,
|
Dialog,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
Flex,
|
Flex,
|
||||||
@@ -68,6 +69,9 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
|
|||||||
const greenPenetration = TankopediaPersistent.use(
|
const greenPenetration = TankopediaPersistent.use(
|
||||||
(state) => state.greenPenetration,
|
(state) => state.greenPenetration,
|
||||||
);
|
);
|
||||||
|
const advancedHighlighting = TankopediaPersistent.use(
|
||||||
|
(state) => state.advancedHighlighting,
|
||||||
|
);
|
||||||
const wireframe = TankopediaPersistent.use((state) => state.wireframe);
|
const wireframe = TankopediaPersistent.use((state) => state.wireframe);
|
||||||
const opaque = TankopediaPersistent.use((state) => state.opaque);
|
const opaque = TankopediaPersistent.use((state) => state.opaque);
|
||||||
const fullScreenAvailable = useFullscreenAvailability();
|
const fullScreenAvailable = useFullscreenAvailability();
|
||||||
@@ -325,6 +329,24 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
|
|||||||
style={{ transform: 'translateX(-50%)' }}
|
style={{ transform: 'translateX(-50%)' }}
|
||||||
>
|
>
|
||||||
{display === TankopediaDisplay.DynamicArmor && (
|
{display === TankopediaDisplay.DynamicArmor && (
|
||||||
|
<>
|
||||||
|
<Flex
|
||||||
|
align="center"
|
||||||
|
gap="2"
|
||||||
|
mb="1"
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
onClick={() => {
|
||||||
|
mutateTankopediaPersistent((draft) => {
|
||||||
|
draft.advancedHighlighting = !draft.advancedHighlighting;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Checkbox checked={advancedHighlighting} />
|
||||||
|
<Text color="gray" size="2">
|
||||||
|
Advanced highlighting
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
<Flex align="center" gap="2">
|
<Flex align="center" gap="2">
|
||||||
<Text color="gray" size="2">
|
<Text color="gray" size="2">
|
||||||
Shooter:
|
Shooter:
|
||||||
@@ -370,8 +392,8 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
|
|||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Flex gap="3" align="center" mt="2">
|
<Flex gap="3" align="center" mt="2">
|
||||||
<SegmentedControl.Root
|
<SegmentedControl.Root
|
||||||
value={`${display}`}
|
value={`${display}`}
|
||||||
|
|||||||
-1
@@ -352,7 +352,6 @@ export function Controls({ naked }: ControlsProps) {
|
|||||||
ref={orbitControls}
|
ref={orbitControls}
|
||||||
enabled={tankopediaEphemeralStore.getState().controlsEnabled}
|
enabled={tankopediaEphemeralStore.getState().controlsEnabled}
|
||||||
enableDamping={false}
|
enableDamping={false}
|
||||||
maxPolarAngle={degToRad(100)}
|
|
||||||
autoRotate={autoRotate}
|
autoRotate={autoRotate}
|
||||||
autoRotateSpeed={1 / 4}
|
autoRotateSpeed={1 / 4}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';
|
|||||||
export interface TankopediaPersistentStore {
|
export interface TankopediaPersistentStore {
|
||||||
wireframe: boolean;
|
wireframe: boolean;
|
||||||
opaque: boolean;
|
opaque: boolean;
|
||||||
|
advancedHighlighting: boolean;
|
||||||
environment: (typeof ENVIRONMENTS)[number];
|
environment: (typeof ENVIRONMENTS)[number];
|
||||||
showGrid: boolean;
|
showGrid: boolean;
|
||||||
greenPenetration: boolean;
|
greenPenetration: boolean;
|
||||||
@@ -33,6 +34,7 @@ export const TankopediaPersistent = createContextualStore(() =>
|
|||||||
subscribeWithSelector<TankopediaPersistentStore>(() => ({
|
subscribeWithSelector<TankopediaPersistentStore>(() => ({
|
||||||
wireframe: false,
|
wireframe: false,
|
||||||
opaque: false,
|
opaque: false,
|
||||||
|
advancedHighlighting: false,
|
||||||
environment: ENVIRONMENTS[0],
|
environment: ENVIRONMENTS[0],
|
||||||
showGrid: true,
|
showGrid: true,
|
||||||
greenPenetration: false,
|
greenPenetration: false,
|
||||||
|
|||||||
Reference in new issue
Block a user