diff --git a/Doc/CHANGELOG.TXT b/Doc/CHANGELOG.TXT index 7c5813243..7e563caec 100644 --- a/Doc/CHANGELOG.TXT +++ b/Doc/CHANGELOG.TXT @@ -54,6 +54,7 @@ General: confusion. * Updated the wormhole cloud effect. * Mouse flight sensitivity made configurable by editing the preferences file. +* Implemented new ECM visual effect. Expansion Pack Development: =========================== diff --git a/Resources/Shaders/oolite-final-hdr.fragment b/Resources/Shaders/oolite-final-hdr.fragment index 6272fda45..1e283c6ec 100644 --- a/Resources/Shaders/oolite-final-hdr.fragment +++ b/Resources/Shaders/oolite-final-hdr.fragment @@ -521,6 +521,25 @@ vec3 CRT(sampler2D inImage, vec2 inCoords) } // ------------------------------------------------------------------------------------------ +// ======================================================================================= +// CRTBadSignal - original at https://www.shadertoy.com/view/ltV3z1 +// ======================================================================================= +vec3 CRTBadSignal(sampler2D inImage, vec2 inCoords) +{ + vec2 uv = inCoords; + float t = uTime; + float fx = 0.001 + 25.0 * abs(sin(t) / 10.0) - mod(1.0 + t, 7.0); + const float s = 50.0; // noise intensity + float x = (floor(uv.x * 300.0)) + (floor(uv.y * 300.0)) * (t * 0.1); + vec4 dtv = vec4(mod((mod(x, 2.0) + 1.0) * (mod(x, 0.0) + 0.0), 0.01) - 0.005) * s; + vec3 col = clamp(vec3(0.1, 0.1, 0.1) + dtv.xyz / fx, vec3(0.0), vec3(0.1)); + + col.xyz += texture(inImage,uv).xyz; + + return col; +} +// ------------------------------------------------------------------------------------------ + // ======================================================================================= // FXAA - original at https://www.shadertoy.com/view/MdyyRt @@ -716,6 +735,12 @@ void main() hdrColor *= exposure; break; case 8: + hdrColor = CRTBadSignal(scene, TexCoords); + bloomColor = CRT(bloomBlur, TexCoords); // yes CRT, not a typo + if(bloom) hdrColor += bloomColor; + hdrColor *= exposure; + break; + case 9: hdrColor = gravLens(scene, TexCoords); bloomColor = gravLens(bloomBlur, TexCoords); if(bloom) hdrColor += bloomColor; diff --git a/Resources/Shaders/oolite-final.fragment b/Resources/Shaders/oolite-final.fragment index f6e66de01..024093a88 100644 --- a/Resources/Shaders/oolite-final.fragment +++ b/Resources/Shaders/oolite-final.fragment @@ -443,6 +443,24 @@ vec3 CRT(sampler2D inImage, vec2 inCoords) } // ------------------------------------------------------------------------------------------ +// ======================================================================================= +// CRTBadSignal - original at https://www.shadertoy.com/view/ltV3z1 +// ======================================================================================= +vec3 CRTBadSignal(sampler2D inImage, vec2 inCoords) +{ + vec2 uv = inCoords; + float t = uTime; + float fx = 0.001 + 25.0 * abs(sin(t) / 10.0) - mod(1.0 + t, 7.0); + const float s = 50.0; // noise intensity + float x = (floor(uv.x * 300.0)) + (floor(uv.y * 300.0 )) * (t * 0.1); + vec4 dtv = vec4(mod((mod(x, 2.0) + 1.0) * (mod(x, 0.0) + 0.0), 0.01) - 0.005) * s; + vec3 col = clamp(vec3(0.1, 0.1, 0.1) + dtv.xyz / fx, vec3(0.0), vec3(0.1)); + + col.xyz += texture(inImage,uv).xyz; + + return col; +} +// ------------------------------------------------------------------------------------------ // ======================================================================================= // FXAA - original at https://www.shadertoy.com/view/MdyyRt @@ -533,6 +551,12 @@ void main() hdrColor *= exposure; break; case 8: + hdrColor = CRTBadSignal(scene, TexCoords); + bloomColor = CRT(bloomBlur, TexCoords); // yes CRT, not a typo + if(bloom) hdrColor += bloomColor; + hdrColor *= exposure; + break; + case 9: hdrColor = gravLens(scene, TexCoords); bloomColor = gravLens(bloomBlur, TexCoords); if(bloom) hdrColor += bloomColor; diff --git a/src/Core/Entities/PlayerEntity.m b/src/Core/Entities/PlayerEntity.m index b7108209d..5d3005871 100644 --- a/src/Core/Entities/PlayerEntity.m +++ b/src/Core/Entities/PlayerEntity.m @@ -2725,6 +2725,8 @@ - (void) doBookkeeping:(double) delta_t STAGE_TRACKING_BEGIN double speed_delta = SHIP_THRUST_FACTOR * thrust; + + static BOOL gettingInterference = NO; OOSunEntity *sun = [UNIVERSE sun]; double external_temp = 0; @@ -2819,6 +2821,29 @@ - (void) doBookkeeping:(double) delta_t ecm_in_operation = NO; } } + + // ecm interference visual effect + if ([UNIVERSE useShaders] && [UNIVERSE ECMVisualFXEnabled]) + { + // we want to start and stop the effect exactly once, not start it + // or stop it on every frame + if ([self scannerFuzziness] > 0.0) + { + if (!gettingInterference) + { + [UNIVERSE setCurrentPostFX:OO_POSTFX_CRTBADSIGNAL]; + gettingInterference = YES; + } + } + else + { + if (gettingInterference) + { + [UNIVERSE terminatePostFX:OO_POSTFX_CRTBADSIGNAL]; + gettingInterference = NO; + } + } + } // Energy Banks and Shields @@ -3930,11 +3955,18 @@ - (void) performDockingUpdates:(OOTimeDelta)delta_t { [self docked]; // bookkeeping for docking } + + // if cloak or ecm visual effects are playing while docking, terminate them + [UNIVERSE terminatePostFX:OO_POSTFX_CLOAK]; + if ([UNIVERSE ECMVisualFXEnabled]) [UNIVERSE terminatePostFX:OO_POSTFX_CRTBADSIGNAL]; } - (void) performDeadUpdates:(OOTimeDelta)delta_t { + [UNIVERSE terminatePostFX:OO_POSTFX_CLOAK]; + if ([UNIVERSE ECMVisualFXEnabled]) [UNIVERSE terminatePostFX:OO_POSTFX_CRTBADSIGNAL]; + [self gameOverFadeToBW]; if ([self shotTime] > kDeadResetTime) @@ -6055,7 +6087,7 @@ - (void) deactivateCloakingDevice if (![self hasCloakingDevice]) return; [super deactivateCloakingDevice]; - [UNIVERSE setCurrentPostFX:[UNIVERSE colorblindMode]]; + [UNIVERSE terminatePostFX:OO_POSTFX_CLOAK]; [UNIVERSE addMessage:DESC(@"cloak-off") forCount:2]; [self playCloakingDeviceOff]; } @@ -6066,11 +6098,15 @@ - (void) deactivateCloakingDevice - (double) scannerFuzziness { double fuzz = 0.0; + /* Fuzziness from ECM bursts */ - double since = [UNIVERSE getTime] - last_ecm_time; - if (since < SCANNER_ECM_FUZZINESS) + if (last_ecm_time > 0.0) { - fuzz += (SCANNER_ECM_FUZZINESS - since) * (SCANNER_ECM_FUZZINESS - since) * 500.0; + double since = [UNIVERSE getTime] - last_ecm_time; + if (since < SCANNER_ECM_FUZZINESS) + { + fuzz += (SCANNER_ECM_FUZZINESS - since) * (SCANNER_ECM_FUZZINESS - since) * 500.0; + } } /* Other causes could go here */ diff --git a/src/Core/Universe.h b/src/Core/Universe.h index 4a4b56d0a..1255b82ca 100644 --- a/src/Core/Universe.h +++ b/src/Core/Universe.h @@ -95,6 +95,7 @@ enum OO_POSTFX_GRAYSCALE, OO_POSTFX_OLDMOVIE, OO_POSTFX_CRT, + OO_POSTFX_CRTBADSIGNAL, OO_POSTFX_ENDOFLIST // keep this for last }; @@ -313,6 +314,8 @@ enum #ifndef NDEBUG double timeAccelerationFactor; #endif + + BOOL ECMVisualFXEnabled; NSMutableArray *activeWormholes; @@ -380,6 +383,7 @@ enum - (int) currentPostFX; - (void) setCurrentPostFX: (int) newCurrentPostFX; +- (void) terminatePostFX:(int) postFX; - (id)initWithGameView:(MyOpenGLView *)gameView; @@ -644,6 +648,9 @@ enum - (double) timeAccelerationFactor; - (void) setTimeAccelerationFactor:(double)newTimeAccelerationFactor; +- (BOOL) ECMVisualFXEnabled; +- (void) setECMVisualFXEnabled:(BOOL)isEnabled; + - (void) filterSortedLists; /////////////////////////////////////// diff --git a/src/Core/Universe.m b/src/Core/Universe.m index 041b8df30..2391285a0 100644 --- a/src/Core/Universe.m +++ b/src/Core/Universe.m @@ -308,6 +308,15 @@ - (void) setCurrentPostFX: (int) newCurrentPostFX _currentPostFX = newCurrentPostFX; } + +- (void) terminatePostFX:(int)postFX +{ + if ([self currentPostFX] == postFX) + { + [self setCurrentPostFX:[self colorblindMode]]; + } +} + - (int) nextColorblindMode:(int) index { if (++index > OO_POSTFX_COLORBLINDNESS_TRITAN) @@ -745,7 +754,9 @@ - (id) initWithGameView:(MyOpenGLView *)inGameView OOLog(@"MSAA.setup", @"Multisample anti-aliasing %@requested.", [inGameView msaa] ? @"" : @"not "); [inGameView setFov:OOClamp_0_max_f([prefs oo_floatForKey:@"fov-value" defaultValue:57.2f], MAX_FOV_DEG) fromFraction:NO]; if ([inGameView fov:NO] < MIN_FOV_DEG) [inGameView setFov:MIN_FOV_DEG fromFraction:NO]; - + + [self setECMVisualFXEnabled:[prefs oo_boolForKey:@"ecm-visual-fx" defaultValue:YES]]; + // Set up speech synthesizer. #if OOLITE_SPEECH_SYNTH #if OOLITE_MAC_OS_X @@ -4802,8 +4813,8 @@ - (BOOL) viewFrustumIntersectsSphereAt:(Vector)position withRadius:(GLfloat)radi - (void) drawUniverse { int currentPostFX = [self currentPostFX]; - BOOL hudSeparateRenderPass = [self useShaders] && (currentPostFX == OO_POSTFX_NONE || (currentPostFX == OO_POSTFX_CLOAK && [self colorblindMode] == OO_POSTFX_NONE)); - NSSize viewSize = [gameView viewSize]; + BOOL hudSeparateRenderPass = [self useShaders] && (currentPostFX == OO_POSTFX_NONE || ((currentPostFX == OO_POSTFX_CLOAK || currentPostFX == OO_POSTFX_CRTBADSIGNAL) && [self colorblindMode] == OO_POSTFX_NONE)); + NSSize viewSize = [gameView viewSize]; OOLog(@"universe.profile.draw", @"%@", @"Begin draw"); if (!no_update) @@ -7383,6 +7394,18 @@ - (void) setTimeAccelerationFactor:(double)newTimeAccelerationFactor #endif +- (BOOL) ECMVisualFXEnabled +{ + return ECMVisualFXEnabled; +} + + +- (void) setECMVisualFXEnabled:(BOOL)isEnabled +{ + ECMVisualFXEnabled = isEnabled; +} + + - (void) filterSortedLists { /*