From 8392bee4a5beb412cc5047976ed33c3dad2f7e51 Mon Sep 17 00:00:00 2001 From: Jens Ayton Date: Thu, 6 May 2010 18:22:53 +0000 Subject: [PATCH] Fade dust motes to clear instead of black when shady. git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@3298 127b21dd-08f5-0310-b4b7-95ae10353056 --- Oolite.xcodeproj/project.pbxproj | 8 +++ Resources/Shaders/oolite-dust.fragment | 32 +++++++++ Resources/Shaders/oolite-dust.vertex | 52 ++++++++++++++ src/Core/Entities/DustEntity.h | 15 +++-- src/Core/Entities/DustEntity.m | 93 ++++++++++++++++++++------ 5 files changed, 174 insertions(+), 26 deletions(-) create mode 100644 Resources/Shaders/oolite-dust.fragment create mode 100644 Resources/Shaders/oolite-dust.vertex diff --git a/Oolite.xcodeproj/project.pbxproj b/Oolite.xcodeproj/project.pbxproj index e110830b..4844ce70 100644 --- a/Oolite.xcodeproj/project.pbxproj +++ b/Oolite.xcodeproj/project.pbxproj @@ -61,6 +61,8 @@ 1A0BF3DE10DAE3490099984D /* python_redux2.dat in Copy Models */ = {isa = PBXBuildFile; fileRef = 1A0BF3DC10DAE3490099984D /* python_redux2.dat */; }; 1A0BF3E010DAE3610099984D /* transporter_redux1.dat in Copy Models */ = {isa = PBXBuildFile; fileRef = 1A0BF3DF10DAE3610099984D /* transporter_redux1.dat */; }; 1A0BF3E210DAE3760099984D /* worm_redux1.dat in Copy Models */ = {isa = PBXBuildFile; fileRef = 1A0BF3E110DAE3760099984D /* worm_redux1.dat */; }; + 1A0C3EDE11933076007935E5 /* oolite-dust.vertex in Copy Shaders */ = {isa = PBXBuildFile; fileRef = 1A0C3EDD1193306B007935E5 /* oolite-dust.vertex */; }; + 1A0C3EEB11933274007935E5 /* oolite-dust.fragment in Copy Shaders */ = {isa = PBXBuildFile; fileRef = 1A0C3EEA11933272007935E5 /* oolite-dust.fragment */; }; 1A0DA2EE0D71D280009B0970 /* OOJSSpecialFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A0DA2EC0D71D280009B0970 /* OOJSSpecialFunctions.h */; }; 1A0DA2EF0D71D280009B0970 /* OOJSSpecialFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DA2ED0D71D280009B0970 /* OOJSSpecialFunctions.m */; }; 1A11273B105994D000DF9D12 /* OOExhaustPlumeEntity.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A112739105994D000DF9D12 /* OOExhaustPlumeEntity.h */; }; @@ -1106,6 +1108,8 @@ dstPath = Shaders; dstSubfolderSpec = 7; files = ( + 1A0C3EEB11933274007935E5 /* oolite-dust.fragment in Copy Shaders */, + 1A0C3EDE11933076007935E5 /* oolite-dust.vertex in Copy Shaders */, 1A6515100CCC9E2E0054D01B /* oolite-standard-vertex.vertex in Copy Shaders */, 1A02FD460EE0490B008F9B09 /* oolite-tangent-space-vertex.vertex in Copy Shaders */, 1A6515110CCC9E2E0054D01B /* oolite-default-shader.fragment in Copy Shaders */, @@ -1168,6 +1172,8 @@ 1A0BF3DC10DAE3490099984D /* python_redux2.dat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = python_redux2.dat; sourceTree = ""; }; 1A0BF3DF10DAE3610099984D /* transporter_redux1.dat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = transporter_redux1.dat; sourceTree = ""; }; 1A0BF3E110DAE3760099984D /* worm_redux1.dat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = worm_redux1.dat; sourceTree = ""; }; + 1A0C3EDD1193306B007935E5 /* oolite-dust.vertex */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.frag; path = "oolite-dust.vertex"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.glsl; }; + 1A0C3EEA11933272007935E5 /* oolite-dust.fragment */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.vert; path = "oolite-dust.fragment"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.glsl; }; 1A0DA2EC0D71D280009B0970 /* OOJSSpecialFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOJSSpecialFunctions.h; sourceTree = ""; }; 1A0DA2ED0D71D280009B0970 /* OOJSSpecialFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSSpecialFunctions.m; sourceTree = ""; }; 1A112739105994D000DF9D12 /* OOExhaustPlumeEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOExhaustPlumeEntity.h; sourceTree = ""; }; @@ -2479,6 +2485,8 @@ 1A65150E0CCC9E220054D01B /* oolite-default-shader.fragment */, 1ADA576710CDB1C300E891B8 /* oolite-default-planet.vertex */, 1ADA576910CDB1C600E891B8 /* oolite-default-planet.fragment */, + 1A0C3EDD1193306B007935E5 /* oolite-dust.vertex */, + 1A0C3EEA11933272007935E5 /* oolite-dust.fragment */, ); path = Shaders; sourceTree = ""; diff --git a/Resources/Shaders/oolite-dust.fragment b/Resources/Shaders/oolite-dust.fragment new file mode 100644 index 00000000..29eec0aa --- /dev/null +++ b/Resources/Shaders/oolite-dust.fragment @@ -0,0 +1,32 @@ +/* + oolite-dust.fragment + + Fragment shader for interplanetary dust. + + + © 2010 Jens Ayton + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. +*/ + + +varying vec4 vColor; + + +void main(void) +{ + gl_FragColor = vColor; +} diff --git a/Resources/Shaders/oolite-dust.vertex b/Resources/Shaders/oolite-dust.vertex new file mode 100644 index 00000000..34888a70 --- /dev/null +++ b/Resources/Shaders/oolite-dust.vertex @@ -0,0 +1,52 @@ +/* + oolite-dust.vertex + + Vertex shader for interplanetary dust. + + + © 2010 Jens Ayton + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. +*/ + + +varying vec4 vColor; + +/* The following macros are provided by Oolite, to ensure that they stay in + sync with the values used in non-shader mode. + +#define OODUST_SCALE_MAX (float(2)) +#define OODUST_SCALE_FACTOR (float(0.002)) +*/ + + +void main(void) +{ + float distance = length(gl_ModelViewMatrix * gl_Vertex); + + /* The original non-shader code fades to black using linear fog, with a + near plane of 500 and a far plane of 1000. + OODUST_SCALE_MAX is far plane/near plane, and OODUST_SCALE_FACTOR + is 1.0/(far plane - near plane). + This gives us a function such that f(x) ≥ 1 when x ≤ near plane, + f(x) ≤ 0 when x ≥ far plane, and a linear ramp in between, which we + then clamp to [0..1]. + */ + float alpha = clamp(OODUST_SCALE_MAX - distance * OODUST_SCALE_FACTOR, 0.0, 1.0); + vColor = vec4(gl_Color.rgb, alpha); + + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; +} diff --git a/src/Core/Entities/DustEntity.h b/src/Core/Entities/DustEntity.h index fd717034..968b6032 100644 --- a/src/Core/Entities/DustEntity.h +++ b/src/Core/Entities/DustEntity.h @@ -25,6 +25,7 @@ MA 02110-1301, USA. */ #import "Entity.h" +#import "OOShaderProgram.h" #define DUST_SCALE 2000 #define DUST_N_PARTICLES 600 @@ -33,13 +34,17 @@ MA 02110-1301, USA. @interface DustEntity: Entity { - OOColor *dust_color; - Vector vertices[DUST_N_PARTICLES]; - GLfloat color_fv[4]; - GLuint displayListName; + OOColor *dust_color; + Vector vertices[DUST_N_PARTICLES]; + GLfloat color_fv[4]; + GLuint displayListName; + +#if OO_SHADERS + OOShaderProgram *shader; +#endif } - (void) setDustColor:(OOColor *) color; -- (OOColor *) dust_color; +- (OOColor *) dustColor; @end diff --git a/src/Core/Entities/DustEntity.m b/src/Core/Entities/DustEntity.m index 1aead154..b4457e17 100644 --- a/src/Core/Entities/DustEntity.m +++ b/src/Core/Entities/DustEntity.m @@ -33,6 +33,10 @@ MA 02110-1301, USA. #import "PlayerEntity.h" +#define FAR_PLANE (DUST_SCALE * 0.50f) +#define NEAR_PLANE (DUST_SCALE * 0.25f) + + // Declare protocol conformance @interface DustEntity (OOGraphicsResetClient) @end @@ -67,10 +71,14 @@ MA 02110-1301, USA. - (void) dealloc { - [dust_color release]; + DESTROY(dust_color); [[OOGraphicsResetManager sharedManager] unregisterClient:self]; OOGL(glDeleteLists(displayListName, 1)); +#if OO_SHADERS + DESTROY(shader); +#endif + [super dealloc]; } @@ -83,7 +91,7 @@ MA 02110-1301, USA. } -- (OOColor *) dust_color +- (OOColor *) dustColor { return dust_color; } @@ -102,7 +110,7 @@ MA 02110-1301, USA. zero_distance = 0.0; - Vector offset = player->position; + Vector offset = [player position]; GLfloat half_scale = DUST_SCALE * 0.50; int vi; for (vi = 0; vi < DUST_N_PARTICLES; vi++) @@ -122,10 +130,31 @@ MA 02110-1301, USA. while (vertices[vi].z - offset.z > half_scale) vertices[vi].z -= DUST_SCALE; } - } +#if OO_SHADERS +- (OOShaderProgram *) shader +{ + if (shader == nil) + { + NSString *prefix = [NSString stringWithFormat: + @"#define OODUST_SCALE_MAX (float(%g))\n" + "#define OODUST_SCALE_FACTOR (float(%g))\n", + FAR_PLANE / NEAR_PLANE, + 1.0f / (FAR_PLANE - NEAR_PLANE)]; + + shader = [[OOShaderProgram shaderProgramWithVertexShaderName:@"oolite-dust.vertex" + fragmentShaderName:@"oolite-dust.fragment" + prefix:prefix + attributeBindings:nil] retain]; + } + + return shader; +} +#endif + + - (void) drawEntity:(BOOL) immediate :(BOOL) translucent { PlayerEntity* player = [PlayerEntity sharedPlayer]; @@ -138,28 +167,37 @@ MA 02110-1301, USA. int vi; GLfloat *fogcolor = [UNIVERSE skyClearColor]; - int dust_size = floor([[UNIVERSE gameView] viewSize].width / 480.0); - if (dust_size < 1.0) - dust_size = 1.0; + int dust_size = [[UNIVERSE gameView] viewSize].width / 480.0; + if (dust_size < 1) dust_size = 1; int line_size = dust_size / 2; - if (line_size < 1.0) - line_size = 1.0; - GLfloat half_scale = DUST_SCALE * 0.50; - GLfloat quarter_scale = DUST_SCALE * 0.25; + if (line_size < 1) line_size = 1; + + if ([UNIVERSE breakPatternHide]) return; // DON'T DRAW - if ([UNIVERSE breakPatternHide]) return; // DON'T DRAW - BOOL warp_stars = [player atHyperspeed]; Vector warp_vector = vector_multiply_scalar([player velocity], 1.0f / HYPERSPEED_FACTOR); - +#if OO_SHADERS + BOOL useShader = [UNIVERSE shaderEffectsLevel] > SHADERS_OFF; +#endif + if (translucent) { - OOGL(glEnable(GL_FOG)); - OOGL(glFogi(GL_FOG_MODE, GL_LINEAR)); - OOGL(glFogfv(GL_FOG_COLOR, fogcolor)); - OOGL(glHint(GL_FOG_HINT, GL_NICEST)); - OOGL(glFogf(GL_FOG_START, quarter_scale)); - OOGL(glFogf(GL_FOG_END, half_scale)); +#if OO_SHADERS + if (useShader) + { + [[self shader] apply]; + OOGL(glEnable(GL_BLEND)); + } + else +#endif + { + OOGL(glEnable(GL_FOG)); + OOGL(glFogi(GL_FOG_MODE, GL_LINEAR)); + OOGL(glFogfv(GL_FOG_COLOR, fogcolor)); + OOGL(glHint(GL_FOG_HINT, GL_NICEST)); + OOGL(glFogf(GL_FOG_START, NEAR_PLANE)); + OOGL(glFogf(GL_FOG_END, FAR_PLANE)); + } // disapply lighting and texture OOGL(glDisable(GL_TEXTURE_2D)); @@ -192,7 +230,16 @@ MA 02110-1301, USA. OOGLEND(); // reapply normal conditions - OOGL(glDisable(GL_FOG)); +#if OO_SHADERS + if (useShader) + { + [OOShaderProgram applyNone]; + } + else +#endif + { + OOGL(glDisable(GL_FOG)); + } } CheckOpenGLErrors(@"DustEntity after drawing %@", self); @@ -206,6 +253,10 @@ MA 02110-1301, USA. OOGL(glDeleteLists(displayListName, 1)); displayListName = 0; } + +#if OO_SHADERS + DESTROY(shader); +#endif }