Rewrite of shader code.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@923 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2007-04-11 20:29:30 +00:00
parent e1d5ba7272
commit 73aafb43e1
29 changed files with 2007 additions and 735 deletions

View File

@ -21,7 +21,7 @@ endif
OBJC_PROGRAM_NAME = oolite
oolite_C_FILES = legacy_random.c strlcpy.c
oolite_OBJC_FILES = Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m TextureStore.m Universe.m OOSound.m SDLMusic.m SDLImage.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m OOSCompiler.m OOSTokenizer.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m
oolite_OBJC_FILES = Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m TextureStore.m Universe.m OOSound.m SDLMusic.m SDLImage.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m OOSCompiler.m OOSTokenizer.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m OOMaterial.m OOShaderMaterial.m OOShaderProgram.m OOShaderUniform.m
include $(GNUSTEP_MAKEFILES)/objc.make
include GNUmakefile.postamble

View File

@ -258,10 +258,15 @@
1A5DBAB00BC000DC00D57389 /* OOSTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A5DBAA40BC000DC00D57389 /* OOSTokenizer.m */; };
1A5DBD580BC17F0900D57389 /* NSStringOOExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A5DBD560BC17F0900D57389 /* NSStringOOExtensions.h */; };
1A5DBD590BC17F0900D57389 /* NSStringOOExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A5DBD570BC17F0900D57389 /* NSStringOOExtensions.m */; };
1A71D85C0BCA88AA00CD5C13 /* OOPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A71D85A0BCA88AA00CD5C13 /* OOPlayer.h */; };
1A71D85D0BCA88AA00CD5C13 /* OOPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A71D85B0BCA88AA00CD5C13 /* OOPlayer.m */; };
1A71D8A10BCA8B6500CD5C13 /* OOLocalPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A71D89F0BCA8B6500CD5C13 /* OOLocalPlayer.h */; };
1A71D8A20BCA8B6500CD5C13 /* OOLocalPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A71D8A00BCA8B6500CD5C13 /* OOLocalPlayer.m */; };
1A71DC350BCBA17000CD5C13 /* OOShaderMaterial.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A71DC330BCBA17000CD5C13 /* OOShaderMaterial.h */; };
1A71DC360BCBA17000CD5C13 /* OOShaderMaterial.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A71DC340BCBA17000CD5C13 /* OOShaderMaterial.m */; };
1A71DDD80BCC0F0400CD5C13 /* OOShaderProgram.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A71DDD60BCC0F0400CD5C13 /* OOShaderProgram.h */; };
1A71DDD90BCC0F0400CD5C13 /* OOShaderProgram.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A71DDD70BCC0F0400CD5C13 /* OOShaderProgram.m */; };
1A71DF0B0BCC3DED00CD5C13 /* OOMaterial.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A71DF090BCC3DED00CD5C13 /* OOMaterial.h */; };
1A71DF0C0BCC3DED00CD5C13 /* OOMaterial.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A71DF0A0BCC3DED00CD5C13 /* OOMaterial.m */; };
1A71DF610BCC46F300CD5C13 /* OOShaderUniform.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A71DF5F0BCC46F300CD5C13 /* OOShaderUniform.h */; };
1A71DF620BCC46F300CD5C13 /* OOShaderUniform.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A71DF600BCC46F300CD5C13 /* OOShaderUniform.m */; };
1A71E44A0BCD5C4200CD5C13 /* material-defaults.plist in Copy Config */ = {isa = PBXBuildFile; fileRef = 1A71E4490BCD5C4200CD5C13 /* material-defaults.plist */; };
1A81F7090A7BAC4D006580AD /* OOCAMusic.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A81F7070A7BAC4D006580AD /* OOCAMusic.m */; };
1A81F70A0A7BAC4D006580AD /* OOCAMusic.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A81F7080A7BAC4D006580AD /* OOCAMusic.h */; };
1A8A37040B95CADD007D20B8 /* PlayerEntityLoadSave.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A37020B95CADD007D20B8 /* PlayerEntityLoadSave.m */; };
@ -478,6 +483,7 @@
dstPath = Config;
dstSubfolderSpec = 7;
files = (
1A71E44A0BCD5C4200CD5C13 /* material-defaults.plist in Copy Config */,
1A34912A0BC25EAA00802DA7 /* world-scripts.plist in Copy Config */,
1A2316EE0B9CFAD700EF0852 /* characters.plist in Copy Config */,
1A2316EF0B9CFAD700EF0852 /* commodities.plist in Copy Config */,
@ -1011,6 +1017,15 @@
1A71D85B0BCA88AA00CD5C13 /* OOPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOPlayer.m; sourceTree = "<group>"; };
1A71D89F0BCA8B6500CD5C13 /* OOLocalPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOLocalPlayer.h; sourceTree = "<group>"; };
1A71D8A00BCA8B6500CD5C13 /* OOLocalPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOLocalPlayer.m; sourceTree = "<group>"; };
1A71DC330BCBA17000CD5C13 /* OOShaderMaterial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOShaderMaterial.h; sourceTree = "<group>"; };
1A71DC340BCBA17000CD5C13 /* OOShaderMaterial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOShaderMaterial.m; sourceTree = "<group>"; };
1A71DDD60BCC0F0400CD5C13 /* OOShaderProgram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOShaderProgram.h; sourceTree = "<group>"; };
1A71DDD70BCC0F0400CD5C13 /* OOShaderProgram.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOShaderProgram.m; sourceTree = "<group>"; };
1A71DF090BCC3DED00CD5C13 /* OOMaterial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOMaterial.h; sourceTree = "<group>"; };
1A71DF0A0BCC3DED00CD5C13 /* OOMaterial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOMaterial.m; sourceTree = "<group>"; };
1A71DF5F0BCC46F300CD5C13 /* OOShaderUniform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOShaderUniform.h; sourceTree = "<group>"; };
1A71DF600BCC46F300CD5C13 /* OOShaderUniform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOShaderUniform.m; sourceTree = "<group>"; };
1A71E4490BCD5C4200CD5C13 /* material-defaults.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = "material-defaults.plist"; sourceTree = "<group>"; };
1A81F7070A7BAC4D006580AD /* OOCAMusic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOCAMusic.m; sourceTree = "<group>"; };
1A81F7080A7BAC4D006580AD /* OOCAMusic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOCAMusic.h; sourceTree = "<group>"; };
1A8A37020B95CADD007D20B8 /* PlayerEntityLoadSave.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayerEntityLoadSave.m; sourceTree = "<group>"; };
@ -1310,6 +1325,7 @@
1A2316E70B9CFAD700EF0852 /* keyconfig.plist */,
1A2316E80B9CFAD700EF0852 /* logcontrol.plist */,
1AED74C70BBA3CAA009410CD /* logcontrol.plist.xml */,
1A71E4490BCD5C4200CD5C13 /* material-defaults.plist */,
1A2316E90B9CFAD700EF0852 /* missiontext.plist */,
1A2316EB0B9CFAD700EF0852 /* shipdata.plist */,
1A2316EC0B9CFAD700EF0852 /* shipyard.plist */,
@ -1600,6 +1616,32 @@
name = "PList & OOS scripting";
sourceTree = "<group>";
};
1A71DDD30BCC0EEF00CD5C13 /* Materials */ = {
isa = PBXGroup;
children = (
1A71DF090BCC3DED00CD5C13 /* OOMaterial.h */,
1A71DF0A0BCC3DED00CD5C13 /* OOMaterial.m */,
1A71DC330BCBA17000CD5C13 /* OOShaderMaterial.h */,
1A71DC340BCBA17000CD5C13 /* OOShaderMaterial.m */,
1A71DDD60BCC0F0400CD5C13 /* OOShaderProgram.h */,
1A71DDD70BCC0F0400CD5C13 /* OOShaderProgram.m */,
1A71DF5F0BCC46F300CD5C13 /* OOShaderUniform.h */,
1A71DF600BCC46F300CD5C13 /* OOShaderUniform.m */,
);
name = Materials;
sourceTree = "<group>";
};
1A71E5230BCD7C4E00CD5C13 /* Player refactoring */ = {
isa = PBXGroup;
children = (
1A71D85A0BCA88AA00CD5C13 /* OOPlayer.h */,
1A71D85B0BCA88AA00CD5C13 /* OOPlayer.m */,
1A71D89F0BCA8B6500CD5C13 /* OOLocalPlayer.h */,
1A71D8A00BCA8B6500CD5C13 /* OOLocalPlayer.m */,
);
name = "Player refactoring";
sourceTree = "<group>";
};
1A8A3BE90B963F02007D20B8 /* Source */ = {
isa = PBXGroup;
children = (
@ -1617,10 +1659,8 @@
25161116099544390037C2E1 /* OOSound.h */,
25161100099544380037C2E1 /* OpenGLSprite.h */,
251610FF099544380037C2E1 /* OpenGLSprite.m */,
1A71D85A0BCA88AA00CD5C13 /* OOPlayer.h */,
1A71D85B0BCA88AA00CD5C13 /* OOPlayer.m */,
1A71D89F0BCA8B6500CD5C13 /* OOLocalPlayer.h */,
1A71D8A00BCA8B6500CD5C13 /* OOLocalPlayer.m */,
1A71E5230BCD7C4E00CD5C13 /* Player refactoring */,
1A71DDD30BCC0EEF00CD5C13 /* Materials */,
1A5DBA980BC000DC00D57389 /* Scripting */,
);
name = Source;
@ -2069,8 +2109,10 @@
1A2A8D3A0BC6765F001E00FB /* EntityOOJavaScriptExtensions.h in Headers */,
1A2A8E030BC67CCC001E00FB /* OOWeakReference.h in Headers */,
1A2A91520BC6BC66001E00FB /* OOJSQuaternion.h in Headers */,
1A71D85C0BCA88AA00CD5C13 /* OOPlayer.h in Headers */,
1A71D8A10BCA8B6500CD5C13 /* OOLocalPlayer.h in Headers */,
1A71DC350BCBA17000CD5C13 /* OOShaderMaterial.h in Headers */,
1A71DDD80BCC0F0400CD5C13 /* OOShaderProgram.h in Headers */,
1A71DF0B0BCC3DED00CD5C13 /* OOMaterial.h in Headers */,
1A71DF610BCC46F300CD5C13 /* OOShaderUniform.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2258,8 +2300,10 @@
1A2A8D3B0BC6765F001E00FB /* EntityOOJavaScriptExtensions.m in Sources */,
1A2A8E040BC67CCC001E00FB /* OOWeakReference.m in Sources */,
1A2A91530BC6BC66001E00FB /* OOJSQuaternion.m in Sources */,
1A71D85D0BCA88AA00CD5C13 /* OOPlayer.m in Sources */,
1A71D8A20BCA8B6500CD5C13 /* OOLocalPlayer.m in Sources */,
1A71DC360BCBA17000CD5C13 /* OOShaderMaterial.m in Sources */,
1A71DDD90BCC0F0400CD5C13 /* OOShaderProgram.m in Sources */,
1A71DF0C0BCC3DED00CD5C13 /* OOMaterial.m in Sources */,
1A71DF620BCC46F300CD5C13 /* OOShaderUniform.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -78,6 +78,7 @@ dataCache.rebuild = inherit;
dataCache.write.success = inherit;
dataCache.write.failed = $error;
dataCache.rebuild.octree = no;
dataCache.willWrite = no;
$dataCacheStatus = yes;
$dataCacheError = $error;
@ -150,14 +151,6 @@ rendering.opengl.error = $error; // Test for and display OpenGL errors
rendering.opengl.version = $troubleShootingDump; // Display renderer version information at startup
rendering.opengl.extensions = $troubleShootingDump; // List OpenGL extensions at startup
rendering.opengl.shader.support = $troubleShootingDump; // Messages about factors influencing availability of OpenGL shaders
rendering.opengl.shader.init = inherit;
rendering.opengl.shader.init.dump = $troubleShootingDump;
rendering.opengl.shader.init.dump.shader = inherit;
rendering.opengl.shader.init.dump.texture = inherit;
rendering.opengl.shader.init.dump.shaderInfo = inherit;
rendering.opengl.shader.init.success = inherit;
rendering.opengl.shader.init.failed = $shaderError;
rendering.opengl.shader.texNameMissing = $shaderError;
rendering.opengl.stateDump = $troubleShootingDump; // Dump of OpenGL state (debug tool, currently unused)
rendering.opengl.shader.uniform = $shaderDebugOn;
@ -241,6 +234,20 @@ script.trace.javaScript.call = inherit; // Prints selector and parameter st
searchPaths.dumpAll = $troubleShootingDump;
$shaderDebug = no;
$shaderError = $error;
shader.load.noShader = $error;
shader.uniform = $shaderDebug;
shader.uniform.set = inherit; // Successfully set a uniform.
shader.uniform.unSet = inherit; // A uniform went unset or was cleared (either because there was no matching uniform in the shader, or the new uniform could not be set up).
shader.uniform.badDescription = inherit; // A uniform specified in shipdata.plist could not be set up, because the configuration could not be understood.
shader.uniform.bind.failed = inherit; // Problem setting up uniform bound to an object property.
shader.vessel.init = $shaderDebug;
shader.compile.vertex.failure = $shaderError;
shader.compile.fragment.failure = $shaderError;
shader.link.failure = $shaderError;
strings.conversion = $scriptError; // Conversion of text to values (vectors, quaternions etc)
strings.conversion.vector = inherit;
strings.conversion.quaternion = inherit;

View File

@ -20,10 +20,12 @@
<string>no</string>
<key>$scriptError</key>
<string>yes</string>
<key>$shaderDebug</key>
<string>no</string>
<key>$shaderDebugOn</key>
<string>no</string>
<key>$shaderError</key>
<string>$scriptError</string>
<string>$error</string>
<key>$soundDebug</key>
<string>no</string>
<key>$soundDebugVerbose</key>
@ -84,6 +86,8 @@
<string>$dataCacheDebug</string>
<key>dataCache.upToDate</key>
<string>$dataCacheStatus</string>
<key>dataCache.willWrite</key>
<string>no</string>
<key>dataCache.write.buildPath.failed</key>
<string>$dataCacheError</string>
<key>dataCache.write.failed</key>
@ -170,24 +174,8 @@
<string>$error</string>
<key>rendering.opengl.extensions</key>
<string>$troubleShootingDump</string>
<key>rendering.opengl.shader.init</key>
<string>inherit</string>
<key>rendering.opengl.shader.init.dump</key>
<string>$troubleShootingDump</string>
<key>rendering.opengl.shader.init.dump.shader</key>
<string>inherit</string>
<key>rendering.opengl.shader.init.dump.shaderInfo</key>
<string>inherit</string>
<key>rendering.opengl.shader.init.dump.texture</key>
<string>inherit</string>
<key>rendering.opengl.shader.init.failed</key>
<string>$shaderError</string>
<key>rendering.opengl.shader.init.success</key>
<string>inherit</string>
<key>rendering.opengl.shader.support</key>
<string>$troubleShootingDump</string>
<key>rendering.opengl.shader.texNameMissing</key>
<string>$shaderError</string>
<key>rendering.opengl.shader.uniform</key>
<string>$shaderDebugOn</string>
<key>rendering.opengl.stateDump</key>
@ -326,6 +314,26 @@
<string>$troubleShootingDump</string>
<key>setup.ship.badEntry.subentities</key>
<string>inherit</string>
<key>shader.compile.fragment.failure</key>
<string>$shaderError</string>
<key>shader.compile.vertex.failure</key>
<string>$shaderError</string>
<key>shader.link.failure</key>
<string>$shaderError</string>
<key>shader.load.noShader</key>
<string>$error</string>
<key>shader.uniform</key>
<string>$shaderDebug</string>
<key>shader.uniform.badDescription</key>
<string>inherit</string>
<key>shader.uniform.bind.failed</key>
<string>inherit</string>
<key>shader.uniform.set</key>
<string>inherit</string>
<key>shader.uniform.unSet</key>
<string>inherit</string>
<key>shader.vessel.init</key>
<string>$shaderDebug</string>
<key>sound.channel.cleanup.failed</key>
<string>$soundError</string>
<key>sound.channel.cleanup.failed.badState</key>

View File

@ -0,0 +1,24 @@
/* Settings for shader system.
While it is possible to override this in the usual fashion, it would not
be a very good idea.
*/
"ship-default-bindings" =
{
"engine_level" = { type = "binding"; value = "speedFactor"; };
"laser_heat_level" = { type = "binding"; value = "laserHeatLevel"; clamped = "YES"; };
"hull_heat_level" = { type = "binding"; value = "hullHeatLevel"; };
"entity_personality" = { type = "binding"; value = "entityPersonality"; };
"entity_personality_int" = { type = "binding"; value = "entityPersonalityInt"; };
};
"ship-prefix-macros" =
{
"OO_ENGINE_LEVEL" = 1;
"OO_ENTITY_PERSONALITY" = 1;
"OO_ENTITY_PERSONALITY_INT" = 1;
"OO_ENTITY_LASER_HEAT_LEVEL" = 1;
"OO_HULL_HEAT_LEVEL" = 1;
"OO_TIME" = 1;
};

View File

@ -256,7 +256,10 @@ static NSString * kOOLogKeyDown = @"input.keyMapping.keyPress.keyDown";
// world's simplest OpenGL optimisations...
#if GL_APPLE_transform_hint
glHint(GL_TRANSFORM_HINT_APPLE, GL_FASTEST);
#endif
glDisable(GL_NORMALIZE);
glDisable(GL_RESCALE_NORMAL);

View File

@ -140,8 +140,10 @@ extern int debug;
isSunlit: 1,
collisionTestFilter: 1,
isSmoothShaded: 1,
throw_sparks: 1,
usingVAR: 1;
#if GL_APPLE_vertex_array_object
usingVAR: 1,
#endif
throw_sparks: 1;
OOScanClass scanClass;
OOEntityStatus status;
@ -217,8 +219,10 @@ extern int debug;
GLuint texture_name[MAX_TEXTURES_PER_ENTITY];
// COMMON OGL STUFF
#if GL_APPLE_vertex_array_object
GLuint gVertexArrayRangeObjects[NUM_VERTEX_ARRAY_RANGES]; // OpenGL's VAR object references
VertexArrayRangeType gVertexArrayRangeData[NUM_VERTEX_ARRAY_RANGES]; // our info about each VAR block
#endif
OOWeakReference *weakSelf;
}
@ -340,13 +344,12 @@ extern int debug;
- (void)dumpState; // General "describe situtation verbosely in log" command.
- (void)dumpSelfState; // Subclasses should override this, not -dumpState, and call throught to super first.
#if GL_APPLE_vertex_array_object
// COMMON OGL ROUTINES
- (BOOL) OGL_InitVAR;
- (void) OGL_AssignVARMemory:(long) size :(void *) data :(Byte) whichVAR;
- (void) OGL_UpdateVAR;
#endif
@end

View File

@ -53,9 +53,11 @@ static NSString * const kOOLogEntityTooManyVertices = @"entity.loadMesh.error.
static NSString * const kOOLogEntityTooManyFaces = @"entity.loadMesh.error.tooManyFaces";
#if GL_APPLE_vertex_array_object
// global flag for VAR
BOOL global_usingVAR;
BOOL global_testForVAR;
#endif
@interface Entity (Private)
@ -827,11 +829,8 @@ BOOL global_testForVAR;
if (immediate)
{
#ifdef GNUSTEP
// TODO: Find out what these APPLE functions can be replaced with
#else
if (usingVAR)
glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#if GL_APPLE_vertex_array_object
if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#endif
//
@ -875,7 +874,7 @@ BOOL global_testForVAR;
}
else
{
OOLog(kOOLogFileNotLoaded, @"ERROR no basefile for entity %@");
OOLog(kOOLogFileNotLoaded, @"ERROR no basefile for entity %@", self);
}
}
if (!isSmoothShaded) glShadeModel(GL_SMOOTH);
@ -963,10 +962,7 @@ BOOL global_testForVAR;
{
// roll out each face and texture in turn
//
int fi,ti ;
if (!UNIVERSE)
return;
int fi,ti;
for (fi = 0; fi < n_faces; fi++)
{
@ -2308,8 +2304,9 @@ BOOL global_testForVAR;
}
// COMMON OGL STUFF
#if GL_APPLE_vertex_array_object
// COMMON OGL STUFF
- (BOOL) OGL_InitVAR
{
short i;
@ -2337,11 +2334,7 @@ BOOL global_testForVAR;
if (!global_usingVAR)
return NO;
#ifdef GNUSTEP
// TODO: Find out what these APPLE functions do
#else
glGenVertexArraysAPPLE(NUM_VERTEX_ARRAY_RANGES, &gVertexArrayRangeObjects[0]);
#endif
// INIT OUR DATA
//
@ -2393,9 +2386,6 @@ BOOL global_testForVAR;
if (!gVertexArrayRangeData[i].forceUpdate)
continue;
#ifdef GNUSTEP
// TODO: find out what non-AAPL OpenGL stuff is equivalent
#else
// BIND THIS VAR OBJECT SO WE CAN DO STUFF TO IT
glBindVertexArrayAPPLE(gVertexArrayRangeObjects[i]);
@ -2420,12 +2410,14 @@ BOOL global_testForVAR;
{
glFlushVertexArrayRangeAPPLE(size, gVertexArrayRangeData[i].dataBlockPtr);
}
#endif
gVertexArrayRangeData[i].forceUpdate = false;
}
}
#endif
// log a list of current states
//
// we need to report on the material properties

View File

@ -354,11 +354,16 @@ static OOCacheManager *sSingleton = nil;
if (caches == nil) return;
OOLog(@"dataCache.willWrite", @"About to write data cache."); // Added for 1.69 to detect possible write-related crash. -- Ahruman
ooliteVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:kCacheKeyVersion];
endianTag = [NSData dataWithBytes:&endianTagValue length:sizeof endianTagValue];
formatVersion = [NSNumber numberWithUnsignedInt:kFormatVersionValue];
pListRep = [self dictionaryOfCaches];
if (ooliteVersion == nil || endianTag == nil || formatVersion == nil || pListRep == nil) return;
if (ooliteVersion == nil || endianTag == nil || formatVersion == nil || pListRep == nil)
{
OOLog(@"dataCache.cantWrite", @"Failed to write data cache -- prerequisites not fulfilled. (This is an internal error, please report it.)");
return;
}
newCache = [NSMutableDictionary dictionaryWithCapacity:4];
[newCache setObject:ooliteVersion forKey:kCacheKeyVersion];

57
src/Core/OOMaterial.h Normal file
View File

@ -0,0 +1,57 @@
/*
OOMaterial.h
A material which can be applied to an OpenGL object, or more accurately, to
the current OpenGL render state.
This is an abstract class; actual materials should be subclasses.
Currently, only shader materials are supported. Direct use of textures should
also be replaced with an OOMaterial subclass.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#import <Foundation/Foundation.h>
#import "OOOpenGL.h"
@interface OOMaterial: NSObject
// Make this the current material.
- (void)apply;
// Make no material the current material, tearing down anything set up by the current material.
+ (void)applyNone;
@end
@interface OOMaterial (OOSubclassInterface)
// Subclass responsibilities - don't call directly.
- (BOOL)doApply; // Override instead of -apply
- (void)unapplyWithNext:(OOMaterial *)next;
// Call at top of dealloc
- (void)willDealloc;
@end

75
src/Core/OOMaterial.m Normal file
View File

@ -0,0 +1,75 @@
/*
OOMaterial.m
This is an abstract class; actual materials should be subclasses.
Currently, only shader materials are supported. Direct use of textures should
also be replaced with an OOMaterial subclass.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#import "OOMaterial.h"
static OOMaterial *sActiveMaterial;
@implementation OOMaterial
- (void)willDealloc
{
if (sActiveMaterial == self)
{
OOLog(@"shader.dealloc.imbalance", @"***** Material deallocated while active, indicating a retain/release imbalance. Expect imminent crash.");
[self unapplyWithNext:nil];
sActiveMaterial = nil;
}
}
// Make this the current GL shader program.
- (void)apply
{
[sActiveMaterial unapplyWithNext:self];
[sActiveMaterial release];
sActiveMaterial = nil;
if ([self doApply])
{
sActiveMaterial = [self retain];
}
}
+ (void)applyNone
{
[sActiveMaterial unapplyWithNext:nil];
[sActiveMaterial release];
sActiveMaterial = nil;
}
- (void)unapply
{
// Do nothing.
}
@end

View File

@ -24,7 +24,10 @@ MA 02110-1301, USA.
*/
#ifndef GNUSTEP
#import "OOCocoa.h"
#if OOLITE_MAC_OS_X
// Apple OpenGL includes...
#include <OpenGL/OpenGL.h>
@ -32,7 +35,11 @@ MA 02110-1301, USA.
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#else
typedef CGLContextObj OOOpenGLContext;
#define OOOpenGLGetCurrentContext CGLGetCurrentContext
#define OOOpenGLSetCurrentContext(ctx) (CGLSetCurrentContext(ctx) == kCGLNoError)
#elif OOLITE_SDL
// SDL OpenGL includes...
@ -45,7 +52,11 @@ MA 02110-1301, USA.
// include an up-to-date version of glext.h
#include <GL/glext.h>
// Define the function pointers for the OpenGL extensions used in the game - this is not required on the Mac, but is on at least Windows.
#if OOLITE_WINDOWS
/* Define the function pointers for the OpenGL extensions used in the game -
this is not required on the Mac, but is on at least Windows.
*/
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
@ -60,6 +71,25 @@ PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
#endif // OOLITE_WINDOWS
/* FIXME: should probably use glXCopyContext() and glXMakeCurrent() on Linux;
there should be an equivalent for Windows. This isn't very urgent since
Oolite doesnt' use distinct contexts, though. I can't see an obvious SDL
version, unfortunately.
*/
typedef uintptr_t OOOpenGLContext; // Opaque context identifier
// OOOpenGLContext OOOpenGLGetCurrentContext(void)
#define OOOpenGLGetCurrentContext() ((OOOpenGLContextID)1UL)
// BOOL OOOpenGLSetCurrentContext(OOOpenGLContext context)
#define OOOpenGLSetCurrentContext(ctx) ((ctx) == 1UL)
#else // Not OS X or SDL
#error OOOpenGL.h: unknown target!
#endif

103
src/Core/OOShaderMaterial.h Normal file
View File

@ -0,0 +1,103 @@
/*
OOShaderMaterial.h
Managers a combination of a shader program, textures and uniforms. Ought to be
a subclass of a hypothetical OOMaterial.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#import "OOMaterial.h"
#import "OOWeakReference.h"
#ifndef NO_SHADERS
@class OOShaderProgram;
@interface OOShaderMaterial: OOMaterial
{
OOShaderProgram *shaderProgram;
NSMutableDictionary *uniforms;
GLuint *textures;
GLuint texCount;
}
/* Set up an OOShaderMaterial.
Configuration should be a dictionary equivalent to an entry in a
shipdata.plist "shaders" dictionary. Specifically, keys OOShaderMaterial
will look for are currently:
textures array of texture file names.
vertex_shader name of vertex shader file.
glsl-vertex vertex shader source (if no vertex_shader).
fragment_shader name of fragment shader file.
glsl-fragment fragment shader source (if no fragment_shader).
glsl fragment shader source (if no glsl-fragment).
uniforms dictionary of uniforms. Values are either reals or
dictionaries containing:
type "int" or "float"
value number
Macros is a dictionary which is converted to macro definitions and
prepended to shader source code. It should be used to specify the
availability if uniforms you tend to register, and other macros such as
bug fix identifiers. For example, the
dictionary:
{ "OO_ENGINE_LEVEL" = 1; }
will be transformed into:
#define OO_ENGINE_LEVEL 1
*/
+ (id)shaderWithConfiguration:(NSDictionary *)configuration macros:(NSDictionary *)macros bindingTarget:(id<OOWeakReferenceSupport>)object;
- (id)initWithConfiguration:(NSDictionary *)configuration macros:(NSDictionary *)macros bindingTarget:(id<OOWeakReferenceSupport>)object;
/* Bind a uniform to a property of an object.
SelectorName should specify a method of source which returns the desired
value; it will be called every time -apply is, assuming uniformName is
used in the shader. (If not, OOShaderMaterial will not track the binding.)
A bound method must return a (signed or unsigned) char, short, int, long,
float or double, and not take any parameters. It will be set as a (signed)
int or a float as appropriate. TODO: support GLSL vector types, and
binding of Vectors and Quaternions.
*/
- (void)bindUniform:(NSString *)uniformName
toObject:(id<OOWeakReferenceSupport>)target
property:(SEL)selector
clamped:(BOOL)clamped;
/* Set a uniform value.
*/
- (void)setUniform:(NSString *)uniformName intValue:(int)value;
- (void)setUniform:(NSString *)uniformName floatValue:(float)value;
/* Add constant uniforms. Same format as uniforms dictionary of configuration
parameter to -initWithConfiguration:macros:. The target parameter is used
for bindings.
*/
-(void)addUniformsFromDictionary:(NSDictionary *)uniformDefs withBindingTarget:(id<OOWeakReferenceSupport>)target;
@end
#endif // NO_SHADERS

380
src/Core/OOShaderMaterial.m Normal file
View File

@ -0,0 +1,380 @@
/*
OOShaderMaterial.m
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#ifndef NO_SHADERS
#import "OOShaderMaterial.h"
#import "OOShaderUniform.h"
#import "OOFunctionAttributes.h"
#import "OOCollectionExtractors.h"
#import "OOShaderProgram.h"
#import "TextureStore.h"
static NSString *MacrosToString(NSDictionary *macros);
@interface OOShaderMaterial (OOPrivate)
- (void)addTexturesFromArray:(NSArray *)textureNames unitCount:(GLint)max;
@end
@implementation OOShaderMaterial
+ (id)shaderWithConfiguration:(NSDictionary *)configuration macros:(NSDictionary *)macros bindingTarget:(id<OOWeakReferenceSupport>)target
{
return [[[self alloc] initWithConfiguration:configuration macros:macros bindingTarget:target] autorelease];
}
- (id)initWithConfiguration:(NSDictionary *)configuration macros:(NSDictionary *)macros bindingTarget:(id<OOWeakReferenceSupport>)target
{
BOOL OK = YES;
NSDictionary *uniformDefs = nil;
NSArray *textureDefs = nil;
NSString *macroString = nil;
NSString *vertexShader = nil;
NSString *fragmentShader = nil;
GLint textureUnits;
NSMutableDictionary *modifiedMacros = nil;
if (configuration == nil) OK = NO;
self = [super init];
if (self == nil) OK = NO;
if (OK && configuration == nil) OK = NO;
if (OK)
{
modifiedMacros = macros ? [macros mutableCopy] : [[NSMutableDictionary alloc] init];
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &textureUnits);
[modifiedMacros setObject:[NSNumber numberWithInt:textureUnits] forKey:@"OO_TEXTURE_UNIT_COUNT"];
macroString = MacrosToString(modifiedMacros);
}
if (OK)
{
vertexShader = [configuration stringForKey:@"vertex_shader" defaultValue:nil];
fragmentShader = [configuration stringForKey:@"fragment_shader" defaultValue:nil];
if (vertexShader != nil || fragmentShader != nil)
{
// If either shader is in an external file, use external-file-based shader (more efficient due to instance sharing)
shaderProgram = [OOShaderProgram shaderProgramWithVertexShaderName:vertexShader fragmentShaderName:fragmentShader prefix:macroString];
}
else
{
// Otherwise, look for inline source
vertexShader = [configuration stringForKey:@"glsl-vertex" defaultValue:nil];
fragmentShader = [configuration stringForKey:@"glsl-fragment" defaultValue:nil];
if (fragmentShader == nil) fragmentShader = [configuration stringForKey:@"glsl" defaultValue:nil];
if (vertexShader != nil || fragmentShader != nil)
{
shaderProgram = [OOShaderProgram shaderProgramWithVertexShaderSource:vertexShader fragmentShaderSource:fragmentShader prefix:macroString];
}
else
{
OOLog(@"shader.load.noShader", @"***** Error: no vertex or fragment shader specified specified in shader dictionary:\n%@", configuration);
}
}
OK = (shaderProgram != nil);
if (OK) [shaderProgram retain];
}
if (OK)
{
// Load uniforms
uniformDefs = [configuration dictionaryForKey:@"uniforms" defaultValue:nil];
textureDefs = [configuration arrayForKey:@"textures" defaultValue:nil];
uniforms = [[NSMutableDictionary alloc] initWithCapacity:[uniformDefs count] + [textureDefs count]];
[self addUniformsFromDictionary:uniformDefs withBindingTarget:target];
// ...and textures, which are a flavour of uniform four our purpose.
[self addTexturesFromArray:textureDefs unitCount:textureUnits];
}
if (!OK)
{
[self release];
self = nil;
}
return self;
}
- (void)dealloc
{
[self willDealloc];
[shaderProgram release];
[uniforms release];
[super dealloc];
}
- (void)bindUniform:(NSString *)uniformName
toObject:(id<OOWeakReferenceSupport>)source
property:(SEL)selector
clamped:(BOOL)clamped
{
OOShaderUniform *uniform = nil;
if (uniformName == nil) return;
uniform = [[OOShaderUniform alloc] initWithName:uniformName shaderProgram:shaderProgram boundToObject:source property:selector clamped:clamped];
if (uniform != nil)
{
OOLog(@"shader.uniform.set", @"Set up uniform %@", uniform);
[uniforms setObject:uniform forKey:uniformName];
[uniform release];
}
else
{
OOLog(@"shader.uniform.unSet", @"Did not set uniform \"%@\"", uniformName);
[uniforms removeObjectForKey:uniformName];
}
}
- (void)setUniform:(NSString *)uniformName intValue:(int)value
{
OOShaderUniform *uniform = nil;
if (uniformName == nil) return;
uniform = [[OOShaderUniform alloc] initWithName:uniformName shaderProgram:shaderProgram intValue:value];
if (uniform != nil)
{
OOLog(@"shader.uniform.set", @"Set up uniform %@", uniform);
[uniforms setObject:uniform forKey:uniformName];
[uniform release];
}
else
{
OOLog(@"shader.uniform.unSet", @"Did not set uniform \"%@\"", uniformName);
[uniforms removeObjectForKey:uniformName];
}
}
- (void)setUniform:(NSString *)uniformName floatValue:(float)value
{
OOShaderUniform *uniform = nil;
if (uniformName == nil) return;
uniform = [[OOShaderUniform alloc] initWithName:uniformName shaderProgram:shaderProgram floatValue:value];
if (uniform != nil)
{
OOLog(@"shader.uniform.set", @"Set up uniform %@", uniform);
[uniforms setObject:uniform forKey:uniformName];
[uniform release];
}
else
{
OOLog(@"shader.uniform.unSet", @"Did not set uniform \"%@\"", uniformName);
[uniforms removeObjectForKey:uniformName];
}
}
-(void)addUniformsFromDictionary:(NSDictionary *)uniformDefs withBindingTarget:(id<OOWeakReferenceSupport>)target
{
NSEnumerator *uniformEnum = nil;
NSString *name = nil;
id definition = nil;
id value = nil;
NSString *type = nil;
GLfloat floatValue;
BOOL gotValue;
OOShaderUniform *uniform = nil;
BOOL clamped;
SEL selector = NULL;
for (uniformEnum = [uniformDefs keyEnumerator]; (name = [uniformEnum nextObject]); )
{
uniform = nil;
definition = [uniformDefs objectForKey:name];
if ([definition isKindOfClass:[NSDictionary class]])
{
value = [definition objectForKey:@"value"];
type = [definition objectForKey:@"type"];
}
else
{
value = definition;
type = @"float";
}
if ([type isEqualToString:@"float"])
{
gotValue = YES;
if ([value respondsToSelector:@selector(floatValue)]) floatValue = [value floatValue];
else if ([value respondsToSelector:@selector(doubleValue)]) floatValue = [value doubleValue];
else if ([value respondsToSelector:@selector(intValue)]) floatValue = [value intValue];
else gotValue = NO;
if (gotValue)
{
[self setUniform:name floatValue:floatValue];
}
}
else if ([type isEqualToString:@"int"])
{
if ([value respondsToSelector:@selector(intValue)])
{
gotValue = YES;
[self setUniform:name intValue:[value intValue]];
}
else gotValue = NO;
}
else if (target != nil && [type isEqualToString:@"binding"])
{
selector = NSSelectorFromString(value);
if (selector)
{
gotValue = YES;
clamped = [definition boolForKey:@"clamped" defaultValue:NO];
[self bindUniform:name toObject:target property:selector clamped:clamped];
}
else gotValue = NO;
}
if (!gotValue)
{
OOLog(@"shader.uniform.badDescription", @"----- Warning: could not bind uniform \"%@\" -- could not interpret definition:\n", name, definition);
}
}
}
- (BOOL)doApply
{
NSEnumerator *uniformEnum = nil;
OOShaderUniform *uniform = nil;
GLint i;
[shaderProgram apply];
for (i = 0; i != texCount; ++i)
{
glActiveTextureARB(GL_TEXTURE0_ARB + i);
glBindTexture(GL_TEXTURE_2D, textures[i]);
}
glActiveTextureARB(GL_TEXTURE0_ARB);
NS_DURING
for (uniformEnum = [uniforms objectEnumerator]; (uniform = [uniformEnum nextObject]); )
{
[uniform apply];
}
NS_HANDLER
/* Supress exceptions during application of bound uniforms. We use a
single exception handler around all uniforms because ObjC
exceptions have some overhead.
*/
NS_ENDHANDLER
return YES;
}
- (void)unapplyWithNext:(OOMaterial *)next
{
if (![next isKindOfClass:[OOShaderMaterial class]]) // Avoid redundant state change
{
[OOShaderProgram applyNone];
}
}
@end
@implementation OOShaderMaterial (OOPrivate)
- (void)addTexturesFromArray:(NSArray *)textureNames unitCount:(GLint)max
{
NSString *name = nil;
unsigned i = 0;
// Allocate space for texture object name array
texCount = MAX(MIN(max, [textureNames count]), 0);
if (texCount == 0) return;
textures = malloc(texCount * sizeof *textures);
if (textures == NULL)
{
texCount = 0;
return;
}
// Set up texture object names and appropriate uniforms
for (i = 0; i != texCount; ++i)
{
[self setUniform:[NSString stringWithFormat:@"tex%u", i] intValue:i];
name = [textureNames objectAtIndex:i];
if ([name isKindOfClass:[NSString class]])
{
OOLog(@"shader.temp.loadTexture", @"Getting texture %@", name);
textures[i] = [TextureStore getTextureNameFor:name];
}
}
}
@end
static NSString *MacrosToString(NSDictionary *macros)
{
NSMutableString *result = nil;
NSEnumerator *macroEnum = nil;
id key = nil, value = nil;
if (macros == nil) return nil;
result = [NSMutableString string];
for (macroEnum = [macros keyEnumerator]; (key = [macroEnum nextObject]); )
{
if (![key isKindOfClass:[NSString class]]) continue;
value = [macros objectForKey:key];
[result appendFormat:@"#define %@ %@\n", key, value];
}
if ([result length] == 0) return nil;
[result appendString:@"\n\n"];
return result;
}
#endif // NO_SHADERS

View File

@ -0,0 +1,61 @@
/*
OOShaderProgram.h
Encapsulates a vertex + fragment shader combo. In general, this should only be
used though OOShaderMaterial. The point of this separation is that more than
one OOShaderMaterial can use the same OOShaderProgram (as long as the shaders
are defined in external files, not strings).
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#ifndef NO_SHADERS
#import <Foundation/Foundation.h>
#import "OOOpenGL.h"
@interface OOShaderProgram: NSObject
{
GLhandleARB program;
GLhandleARB vertexShader;
GLhandleARB fragmentShader;
NSString *key;
}
// Loads a shader from a file, caching and sharing shader program instances.
+ (id)shaderProgramWithVertexShaderName:(NSString *)vertexShaderName
fragmentShaderName:(NSString *)fragmentShaderName
prefix:(NSString *)prefixString;
// Loads a shader from memory, always generating a new instance.
+ (id)shaderProgramWithVertexShaderSource:(NSString *)vertexShaderSource
fragmentShaderSource:(NSString *)fragmentShaderSource
prefix:(NSString *)prefixString;
- (void)apply;
+ (void)applyNone;
- (GLhandleARB)program;
@end
#endif // NO_SHADERS

313
src/Core/OOShaderProgram.m Normal file
View File

@ -0,0 +1,313 @@
/*
OOShaderProgram.m
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#ifndef NO_SHADERS
#import "OOShaderProgram.h"
#import "OOFunctionAttributes.h"
#import "OOStringParsing.h"
#import "ResourceManager.h"
static NSMutableDictionary *sShaderCache = nil;
static OOShaderProgram *sActiveProgram = nil;
static BOOL GetShaderSource(NSString *fileName, NSString *shaderType, NSString *prefix, NSString **outResult);
static NSString *GetGLSLInfoLog(GLhandleARB shaderObject);
@interface OOShaderProgram (OOPrivate)
- (id)initWithVertexShaderSource:(NSString *)vertexSource fragmentShaderSource:(NSString *)fragmentSource key:(NSString *)key;
@end
@implementation OOShaderProgram
+ (id)shaderProgramWithVertexShaderName:(NSString *)vertexShaderName
fragmentShaderName:(NSString *)fragmentShaderName
prefix:(NSString *)prefixString
{
NSString *key = nil;
OOShaderProgram *program = nil;
NSString *vertexSource = nil;
NSString *fragmentSource = nil;
if ([prefixString length] == 0) prefixString = nil;
// Use cache to avoid creating duplicate shader programs -- saves on GPU resources and potentially state changes.
key = [NSString stringWithFormat:@"vertex:%@\nfragment:%@\n----\n%@", vertexShaderName, fragmentShaderName, prefixString ?: @""];
program = [[sShaderCache objectForKey:key] pointerValue];
if (program == nil)
{
// No cached program; create one...
if (!GetShaderSource(vertexShaderName, @"vertex", prefixString, &vertexSource)) return nil;
if (!GetShaderSource(fragmentShaderName, @"fragment", prefixString, &fragmentSource)) return nil;
program = [[OOShaderProgram alloc] initWithVertexShaderSource:vertexSource fragmentShaderSource:fragmentSource key:key];
if (program != nil)
{
// ...and add it to the cache
[program autorelease];
if (sShaderCache == nil) sShaderCache = [[NSMutableDictionary alloc] init];
[sShaderCache setObject:[NSValue valueWithPointer:program] forKey:key]; // Use NSValue so dictionary doesn't retain program
}
}
return program;
}
+ (id)shaderProgramWithVertexShaderSource:(NSString *)vertexShaderSource
fragmentShaderSource:(NSString *)fragmentShaderSource
prefix:(NSString *)prefixString
{
if (prefixString != nil)
{
if (vertexShaderSource != nil) vertexShaderSource = [prefixString stringByAppendingString:vertexShaderSource];
if (fragmentShaderSource != nil) fragmentShaderSource = [prefixString stringByAppendingString:fragmentShaderSource];
}
return [[[self alloc] initWithVertexShaderSource:vertexShaderSource fragmentShaderSource:fragmentShaderSource key:nil] autorelease];
}
- (void)dealloc
{
if (EXPECT_NOT(sActiveProgram == self))
{
OOLog(@"shader.dealloc.imbalance", @"***** OOShaderProgram deallocated while active, indicating a retain/release imbalance. Expect imminent crash.");
[OOShaderProgram applyNone];
}
if (key != nil)
{
[sShaderCache removeObjectForKey:key];
[key release];
}
glDeleteObjectARB(program);
glDeleteObjectARB(vertexShader);
glDeleteObjectARB(fragmentShader);
[super dealloc];
}
- (void)apply
{
if (sActiveProgram != self)
{
[sActiveProgram release];
sActiveProgram = [self retain];
glUseProgramObjectARB(program);
}
}
+ (void)applyNone
{
if (sActiveProgram != nil)
{
[sActiveProgram release];
sActiveProgram = nil;
glUseProgramObjectARB(NULL_SHADER);
}
}
- (GLhandleARB)program
{
return program;
}
@end
@implementation OOShaderProgram (OOPrivate)
- (id)initWithVertexShaderSource:(NSString *)vertexSource fragmentShaderSource:(NSString *)fragmentSource key:(NSString *)inKey
{
BOOL OK = YES;
const GLcharARB *sourceString = nil;
GLint compileStatus;
self = [super init];
if (self == nil) OK = NO;
if (OK && vertexSource == nil && fragmentSource == nil) OK = NO; // Must have at least one shader!
if (OK && vertexSource != nil)
{
// Compile vertex shader.
vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
if (vertexShader != NULL_SHADER)
{
sourceString = [vertexSource lossyCString];
glShaderSourceARB(vertexShader, 1, &sourceString, NULL);
glCompileShaderARB(vertexShader);
glGetObjectParameterivARB(vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
if (compileStatus != GL_TRUE)
{
OOLog(@"shader.compile.vertex.failure", @"***** GLSL %s shader compilation failed:\n>>>>> GLSL log:\n%@\n\n>>>>> GLSL source code:\n%@\n", "vertex", GetGLSLInfoLog(vertexShader), vertexSource);
OK = NO;
}
}
else OK = NO;
}
if (OK && fragmentSource != nil)
{
// Compile fragment shader.
fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
if (fragmentShader != NULL_SHADER)
{
sourceString = [fragmentSource lossyCString];
glShaderSourceARB(fragmentShader, 1, &sourceString, NULL);
glCompileShaderARB(fragmentShader);
glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
if (compileStatus != GL_TRUE)
{
OOLog(@"shader.compile.fragment.failure", @"***** GLSL %s shader compilation failed:\n>>>>> GLSL log:\n%@\n\n>>>>> GLSL source code:\n%@\n", "fragment", GetGLSLInfoLog(fragmentShader), fragmentSource);
OK = NO;
}
}
else OK = NO;
}
if (OK)
{
// Link shader.
program = glCreateProgramObjectARB();
if (program != NULL_SHADER)
{
if (vertexShader != NULL_SHADER) glAttachObjectARB(program, vertexShader);
if (fragmentShader != NULL_SHADER) glAttachObjectARB(program, fragmentShader);
glLinkProgramARB(program);
glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &compileStatus);
if (compileStatus != GL_TRUE)
{
OOLog(@"shader.link.failure", @"***** GLSL shader linking failed:\n>>>>> GLSL log:\n%@\n", GetGLSLInfoLog(program));
OK = NO;
}
}
else OK = NO;
}
if (OK)
{
key = [inKey copy];
}
if (!OK)
{
if (vertexShader) glDeleteObjectARB(vertexShader);
if (fragmentShader) glDeleteObjectARB(fragmentShader);
if (program) glDeleteObjectARB(program);
[self release];
self = nil;
}
return self;
}
@end
/* Attempt to load fragment or vertex shader source from a file.
Returns YES if source was loaded or no shader was specified, and NO if an
external shader was specified but could not be found.
*/
static BOOL GetShaderSource(NSString *fileName, NSString *shaderType, NSString *prefix, NSString **outResult)
{
NSString *result = nil;
NSString *shaderName = nil;
NSArray *extensions = nil;
NSEnumerator *extEnum = nil;
NSString *extension = nil;
NSString *nameWithExtension = nil;
result = [ResourceManager stringFromFilesNamed:fileName inFolder:@"Shaders"];
if (result == nil)
{
extensions = [NSArray arrayWithObjects:shaderType, [shaderType substringToIndex:4], nil]; // vertex and vert, or fragment and frag
// Futureproofing -- in future, we may wish to support automatic selection between supported shader languages.
if (![shaderName pathHasExtensionInArray:extensions])
{
for (extEnum = [extensions objectEnumerator]; (extension = [extEnum nextObject]); )
{
nameWithExtension = [fileName stringByAppendingPathExtension:extension];
result = [ResourceManager stringFromFilesNamed:nameWithExtension
inFolder:@"Shaders"];
if (result != nil) break;
}
}
if (result == nil)
{
OOLog(kOOLogFileNotFound, @"GLSL ERROR: failed to find fragment program %@.", shaderName);
return NO;
}
}
if (result != nil && prefix != nil)
{
result = [prefix stringByAppendingString:result];
}
if (outResult != NULL) *outResult = result;
return YES;
}
static NSString *GetGLSLInfoLog(GLhandleARB shaderObject)
{
GLint length;
GLcharARB *log = nil;
NSString *result = nil;
if (shaderObject == NULL_SHADER) return nil;
glGetObjectParameterivARB(shaderObject, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
log = malloc(length);
if (log == NULL)
{
length = 1024;
log = malloc(length);
if (log == NULL) return @"<out of memory>";
}
glGetInfoLogARB(shaderObject, length, NULL, log);
result = [NSString stringWithUTF8String:log];
if (result == nil) result = [[[NSString alloc] initWithBytes:log length:length - 1 encoding:NSISOLatin1StringEncoding] autorelease];
return result;
}
#endif // NO_SHADERS

View File

@ -0,0 +1,60 @@
/*
OOShaderUniform.h
Manages a uniform variable for OOShaderMaterial.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#ifndef NO_SHADERS
#import "OOShaderMaterial.h"
@interface OOShaderUniform: NSObject
{
NSString *name;
GLint location;
BOOL isBinding;
uint8_t type;
union
{
GLint constInt;
GLfloat constFloat;
struct
{
OOWeakReference *object;
SEL selector;
IMP method;
BOOL clamped;
} binding;
} value;
}
- (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram intValue:(int)constValue;
- (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram floatValue:(int)constValue;
- (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram boundToObject:(id<OOWeakReferenceSupport>)source property:(SEL)selector clamped:(BOOL)clamped;
- (void)apply;
@end
#endif // NO_SHADERS

394
src/Core/OOShaderUniform.m Normal file
View File

@ -0,0 +1,394 @@
/*
OOShaderUniform.m
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
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.
*/
#ifndef NO_SHADERS
#import "OOShaderUniform.h"
#import "OOShaderProgram.h"
#import "OOFunctionAttributes.h"
#import <string.h>
#import "OOMaths.h"
typedef enum
{
kOOShaderUniformTypeChar,
kOOShaderUniformTypeShort,
kOOShaderUniformTypeInt,
kOOShaderUniformTypeLong,
kOOShaderUniformTypeFloat,
kOOShaderUniformTypeDouble
// Vector and matrix types may be added in future.
} OOShaderUniformType;
typedef char (*CharReturnMsgSend)(id, SEL);
typedef short (*ShortReturnMsgSend)(id, SEL);
typedef int (*IntReturnMsgSend)(id, SEL);
typedef long (*LongReturnMsgSend)(id, SEL);
typedef float (*FloatReturnMsgSend)(id, SEL);
typedef double (*DoubleReturnMsgSend)(id, SEL);
OOINLINE BOOL ValidBindingType(OOShaderUniformType type)
{
return kOOShaderUniformTypeInt <= type && type <= kOOShaderUniformTypeDouble;
}
@interface OOShaderUniform (OOPrivate)
- (void)applySimple;
- (void)applyBinding;
@end
@implementation OOShaderUniform
- (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram intValue:(int)constValue
{
BOOL OK = YES;
if (EXPECT_NOT(uniformName == NULL || shaderProgram == NULL)) OK = NO;
if (OK)
{
self = [super init];
if (self == nil) OK = NO;
}
if (OK)
{
location = glGetUniformLocationARB([shaderProgram program], [uniformName lossyCString]);
if (location == -1) OK = NO;
}
if (OK)
{
name = [uniformName retain];
type = kOOShaderUniformTypeInt;
value.constInt = constValue;
}
if (!OK)
{
[self release];
self = nil;
}
return self;
}
- (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram floatValue:(int)constValue
{
BOOL OK = YES;
if (EXPECT_NOT(uniformName == NULL || shaderProgram == NULL)) OK = NO;
if (OK)
{
self = [super init];
if (self == nil) OK = NO;
}
if (OK)
{
location = glGetUniformLocationARB([shaderProgram program], [uniformName lossyCString]);
if (location == -1) OK = NO;
}
if (OK)
{
name = [uniformName retain];
type = kOOShaderUniformTypeFloat;
value.constFloat = constValue;
}
if (!OK)
{
[self release];
self = nil;
}
return self;
}
- (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram boundToObject:(id<OOWeakReferenceSupport>)source property:(SEL)selector clamped:(BOOL)clamped
{
BOOL OK = YES;
NSMethodSignature *sig = nil;
unsigned argCount;
NSString *methodProblem = nil;
const char *typeCode = nil;
if (EXPECT_NOT(uniformName == NULL || shaderProgram == NULL || source == nil || selector == NULL)) OK = NO;
if (OK)
{
self = [super init];
if (self == nil) OK = NO;
}
if (OK)
{
location = glGetUniformLocationARB([shaderProgram program], [uniformName lossyCString]);
if (location == -1) OK = NO;
}
// Check to see if it's a valid method.
if (OK)
{
if (![source respondsToSelector:selector])
{
methodProblem = @"target does not respond to selector";
OK = NO;
}
}
if (OK)
{
value.binding.method = [(id)source methodForSelector:selector];
if (value.binding.method == NULL)
{
methodProblem = @"could not retrieve method implementation";
OK = NO;
}
}
if (OK)
{
sig = [(id)source methodSignatureForSelector:selector];
if (sig == nil)
{
methodProblem = @"could not retrieve method signature";
OK = NO;
}
}
if (OK)
{
argCount = [sig numberOfArguments];
if (argCount != 2) // "no-arguments" methods actually take two arguments, self and _msg.
{
methodProblem = @"only methods which do not require arguments may be bound to";
OK = NO;
}
}
if (OK)
{
typeCode = [sig methodReturnType];
if (0 == strcmp("f", typeCode)) type = kOOShaderUniformTypeFloat;
else if (0 == strcmp("d", typeCode)) type = kOOShaderUniformTypeDouble;
else if (0 == strcmp("c", typeCode) || 0 == strcmp("C", typeCode)) type = kOOShaderUniformTypeChar; // Signed or unsigned
else if (0 == strcmp("s", typeCode) || 0 == strcmp("S", typeCode)) type = kOOShaderUniformTypeShort;
else if (0 == strcmp("i", typeCode) || 0 == strcmp("I", typeCode)) type = kOOShaderUniformTypeInt;
else if (0 == strcmp("l", typeCode) || 0 == strcmp("L", typeCode)) type = kOOShaderUniformTypeLong;
else
{
methodProblem = [NSString stringWithFormat:@"unsupported type \"%s\"", typeCode];
}
}
// If we're still OK, it's a bindable method.
if (OK)
{
name = [uniformName retain];
isBinding = YES;
value.binding.object = [source weakRetain];
value.binding.selector = selector;
value.binding.clamped = clamped;
}
if (!OK)
{
if (methodProblem != nil)
{
OOLog(@"shader.uniform.bind.failed", @"***** Shader error: could not bind uniform \"%@\" to -[%@ %s] (%@).", uniformName, [source class], selector, methodProblem);
}
[self release];
self = nil;
}
return self;
}
- (void)dealloc
{
[name release];
if (isBinding) [value.binding.object release];
[super dealloc];
}
- (NSString *)description
{
NSString *valueDesc = nil;
NSString *valueType = nil;
id object;
if (isBinding)
{
object = [value.binding.object weakRefUnderlyingObject];
if (object != nil)
{
valueDesc = [NSString stringWithFormat:@"[<%@ %p> %@]", [object class], value.binding.object, NSStringFromSelector(value.binding.selector)];
}
else
{
valueDesc = @"0";
}
}
else
{
switch (type)
{
case kOOShaderUniformTypeInt:
valueDesc = [NSString stringWithFormat:@"%i", value.constInt];
break;
case kOOShaderUniformTypeFloat:
valueDesc = [NSString stringWithFormat:@"%g", value.constFloat];
break;
}
}
switch (type)
{
case kOOShaderUniformTypeChar:
case kOOShaderUniformTypeShort:
case kOOShaderUniformTypeInt:
case kOOShaderUniformTypeLong:
valueType = @"int";
break;
case kOOShaderUniformTypeFloat:
case kOOShaderUniformTypeDouble:
valueType = @"float";
break;
}
if (valueType == nil) valueDesc = @"INVALID";
if (valueDesc == nil) valueDesc = @"INVALID";
/* Examples:
<OOShaderUniform 0xf00>{1: int tex1 = 1;}
<OOShaderUniform 0xf00>{3: float laser_heat_level = [<ShipEntity 0xba8> laserHeatLevel];}
*/
return [NSString stringWithFormat:@"<%@ %p>{%i: %@ %@ = %@;}", [self class], self, location, valueType, name, valueDesc];
}
- (void)apply
{
if (isBinding) [self applyBinding];
else [self applySimple];
}
@end
@implementation OOShaderUniform (OOPrivate)
- (void)applySimple
{
switch (type)
{
case kOOShaderUniformTypeInt:
glUniform1iARB(location, value.constInt);
break;
case kOOShaderUniformTypeFloat:
glUniform1fARB(location, value.constFloat);
break;
}
}
- (void)applyBinding
{
id object = nil;
int iVal;
float fVal;
BOOL fp = NO;
/* Design note: if the object has been dealloced, or an exception occurs,
do nothing. Shaders can specify a default value for uniforms, which
will be used when no setting has been provided by the host program.
I considered clearing value.binding.object if the underlying object is
gone, but adding code to save a small amount of spacein a case that
shouldn't occur in normal usage is silly.
*/
object = [value.binding.object weakRefUnderlyingObject];
if (object == nil) return;
switch (type)
{
case kOOShaderUniformTypeChar:
iVal = ((CharReturnMsgSend)value.binding.method)(object, value.binding.selector);
break;
case kOOShaderUniformTypeShort:
iVal = ((ShortReturnMsgSend)value.binding.method)(object, value.binding.selector);
break;
case kOOShaderUniformTypeInt:
iVal = ((IntReturnMsgSend)value.binding.method)(object, value.binding.selector);
break;
case kOOShaderUniformTypeLong:
iVal = ((LongReturnMsgSend)value.binding.method)(object, value.binding.selector);
break;
case kOOShaderUniformTypeFloat:
fVal = ((FloatReturnMsgSend)value.binding.method)(object, value.binding.selector);
fp = YES;
break;
case kOOShaderUniformTypeDouble:
fVal = ((DoubleReturnMsgSend)value.binding.method)(object, value.binding.selector);
fp = YES;
break;
}
if (!fp)
{
if (EXPECT_NOT(value.binding.clamped)) iVal = iVal ? 1 : 0;
glUniform1iARB(location, iVal);
}
else
{
if (EXPECT_NOT(value.binding.clamped)) fVal = OOClamp_0_1_f(fVal);
glUniform1fARB(location, fVal);
}
}
@end
#endif // NO_SHADERS

View File

@ -14,7 +14,9 @@ Client use is extremely simple: to get a weak reference to the object, call
-weakRetain and use the returned proxy instead of the actual object. When
finished, release the proxy. Messages sent to the proxy will be forwarded as
long as the underlying object exists; beyond that, they will act exactly like
messages to nil. Example:
messages to nil. (IMPORTANT: this means messages returning floating-point or
struct values have undefined return values, so use -weakRefObjectStillExists
or -weakRefUnderlyingObject in such cases.) Example:
@interface ThingWatcher: NSObject
{

View File

@ -1304,7 +1304,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle
Frame zero;
zero.q_rotation = shipQrotation;
int dam = [ship damage];
GLfloat flare_length = [ship speed_factor];
GLfloat flare_length = [ship speedFactor];
if (!flare_length) // don't draw if there's no fire!
return;
@ -1824,7 +1824,7 @@ GLuint tfan2[10] = { 33, 25, 26, 27, 28, 29, 30, 31, 32, 25}; // final fan 64..7
if (!ship)
return;
if ([ship speed_factor] <= 0.0) // don't draw if there's no fire!
if ([ship speedFactor] <= 0.0) // don't draw if there's no fire!
return;
glPopMatrix(); // restore absolute positioning

View File

@ -532,7 +532,7 @@ void setUpSinTable()
isTextured = (textureName != 0);
isShadered = NO;
#ifndef NO_SHADERS
#if OLD_SHADERS
if (UNIVERSE)
{
NSDictionary* shader_info = [[UNIVERSE descriptions] objectForKey:@"planet-surface-shader"];
@ -545,6 +545,7 @@ void setUpSinTable()
NSLog(@"TESTING: planet-surface-shader: %d normalMapTextureName: %d", (int)shader_program, (int)normalMapTextureName);
}
}
#endif
#endif
}
else
@ -1786,11 +1787,8 @@ void drawActiveCorona (double inner_radius, double outer_radius, int step, doubl
- (void) drawModelWithVertexArraysAndSubdivision: (int) subdivide
{
#ifdef GNUSTEP
// TODO: Find a suitable replacement fn for APPLE
#else
if (usingVAR)
glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#if GL_APPLE_vertex_array_object
if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#endif
glDrawElements( GL_TRIANGLES, 3 * n_triangles[subdivide], GL_UNSIGNED_INT, &vertexdata.index_array[triangle_start[subdivide]]);

View File

@ -128,11 +128,8 @@ Ringdata ringentity;
{
if (immediate)
{
#ifdef GNUSTEP
// TODO: replace APPLE function call
#else
if (usingVAR)
glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#if GL_APPLE_vertex_array_object
if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#endif
glEnableClientState(GL_VERTEX_ARRAY);

View File

@ -280,8 +280,12 @@ MA 02110-1301, USA.
int debug_flag;
int debug_condition;
#ifdef OLD_SHADERS
// shaders
NSMutableDictionary *shader_info;
#else
NSMutableDictionary *materials;
#endif
uint16_t entity_personality; // Per-entity random number. Used for shaders, maybe scripting at some point.
}
@ -469,7 +473,7 @@ MA 02110-1301, USA.
- (GLfloat) flight_yaw;
- (GLfloat) flight_speed;
- (GLfloat) max_flight_speed;
- (GLfloat) speed_factor;
- (GLfloat) speedFactor;
- (void) setTemperature:(GLfloat) value;
- (void) setHeatInsulation:(GLfloat) value;
@ -506,8 +510,10 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other);
- (NSComparisonResult) compareBeaconCodeWith:(ShipEntity*) other;
- (GLfloat)laserHeatLevel;
- (GLfloat)hullHeatLevel;
- (float)laserHeatLevel;
- (float)hullHeatLevel;
- (float)entityPersonality;
- (int)entityPersonalityInt;
- (void)setSuppressExplosion:(BOOL)suppress;
@ -640,17 +646,14 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role);
- (void) sendCoordinatesToPilot;
- (void) pilotArrived;
/****************************************************************
straight c stuff
****************************************************************/
BOOL ship_canCollide (ShipEntity* ship);
- (Entity *)entityForShaderProperties;
@end
BOOL ship_canCollide (ShipEntity* ship);
@interface OOCacheManager (Octree)
+ (Octree *)octreeForModel:(NSString *)inKey;

View File

@ -28,9 +28,13 @@ MA 02110-1301, USA.
#import "OOMaths.h"
#import "Universe.h"
#import "TextureStore.h"
#import "OOShaderMaterial.h"
#import "ResourceManager.h"
#import "OOStringParsing.h"
#import "OOCollectionExtractors.h"
#import "OOConstToString.h"
#import "NSScannerOOExtensions.h"
#import "OOCharacter.h"
#import "OOBrain.h"
@ -38,7 +42,6 @@ MA 02110-1301, USA.
#import "Geometry.h"
#import "Octree.h"
#import "NSScannerOOExtensions.h"
#import "OOColor.h"
#import "ParticleEntity.h"
@ -57,11 +60,6 @@ extern NSString * const kOOLogSyntaxAddShips;
static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.changed";
static NSString * const kOOLogOpenGLVersion = @"rendering.opengl.version";
static NSString * const kOOLogOpenGLShaderSupport = @"rendering.opengl.shader.support";
static NSString * const kOOLogShaderInit = @"rendering.opengl.shader.init";
static NSString * const kOOLogShaderInitDumpShader = @"rendering.opengl.shader.init.dump.shader";
static NSString * const kOOLogShaderInitDumpTexture = @"rendering.opengl.shader.init.dump.texture";
static NSString * const kOOLogShaderInitDumpShaderInfo = @"rendering.opengl.shader.init.dump.shaderInfo";
static NSString * const kOOLogShaderTextureNameMissing = @"rendering.opengl.shader.texNameMissing";
#ifdef GNUSTEP
void loadOpenGLFunctions()
@ -84,7 +82,9 @@ void loadOpenGLFunctions()
#endif
#if OLD_SHADERS
static void ApplyConstantUniforms(NSDictionary *uniforms, GLhandleARB shaderProgram);
#endif
@implementation ShipEntity
@ -454,7 +454,12 @@ static void ApplyConstantUniforms(NSDictionary *uniforms, GLhandleARB shaderProg
[octree autorelease];
#ifndef NO_SHADERS
#if OLD_SHADERS
[shader_info release];
#endif
#endif
[materials release];
[super dealloc];
}
@ -2709,331 +2714,227 @@ void testForShaders()
#endif
}
- (void) initialiseTextures
{
[super initialiseTextures];
NSDictionary *shaderDefs = nil;
NSEnumerator *shaderEnum = nil;
NSString *shaderKey = nil;
NSDictionary *shaderConfig = nil;
OOShaderMaterial *shader = nil;
static NSDictionary *macros = nil;
static NSDictionary *defaultBindings = nil;
Entity *propertyEntity = nil;
NSDictionary *materialDefaults = nil;
if (testForShaderSupport)
testForShaders();
if ([shipinfoDictionary objectForKey:@"shaders"] && shaders_supported)
[super initialiseTextures];
if (testForShaderSupport) testForShaders();
if (!shaders_supported) return;
shaderDefs = [shipinfoDictionary objectForKey:@"shaders"];
if (shaderDefs)
{
#ifndef NO_SHADERS
// initialise textures in shaders
if (!shader_info)
shader_info = [[NSMutableDictionary dictionary] retain];
OOLog(kOOLogShaderInit, @"Initialising shaders for %@", self);
OOLogIndentIf(kOOLogShaderInit);
NSDictionary *shaders = [shipinfoDictionary objectForKey:@"shaders"];
NSEnumerator *shaderEnum = nil;
NSString *shaderKey = nil;
for (shaderEnum = [shaders keyEnumerator]; (shaderKey = [shaderEnum nextObject]); )
if (materials)
{
NSDictionary* shader = [shaders objectForKey:shaderKey];
NSArray* shader_textures = [shader objectForKey:@"textures"];
NSMutableArray* textureNames = [NSMutableArray array];
OOLog(kOOLogShaderInitDumpShader, @"Shader: initialising shader for %@ : %@", shaderKey, shader);
int ti;
for (ti = 0; ti < [shader_textures count]; ti ++)
OOLog(@"shipEntity.squashRecycling", @"Hmm, shaders is non-nil for %@.", self);
[materials release];
}
materials = [[NSMutableDictionary alloc] init];
OOLog(@"shader.vessel.init", @"Initialising shaders for %@", self);
OOLogIndentIf(@"shader.vessel.init");
if (macros == nil)
{
// Set up macros and bindings used for all ship shaders
materialDefaults = [ResourceManager dictionaryFromFilesNamed:@"material-defaults.plist" inFolder:@"Config" andMerge:YES];
macros = [[materialDefaults dictionaryForKey:@"ship-prefix-macros" defaultValue:[NSDictionary dictionary]] retain];
defaultBindings = [[materialDefaults dictionaryForKey:@"ship-default-bindings" defaultValue:[NSDictionary dictionary]] retain];
}
propertyEntity = [self entityForShaderProperties];
for (shaderEnum = [shaderDefs keyEnumerator]; (shaderKey = [shaderEnum nextObject]); )
{
shaderConfig = [shaderDefs dictionaryForKey:shaderKey defaultValue:nil];
if (shaderConfig != nil)
{
GLuint tn = [TextureStore getTextureNameFor: (NSString*)[shader_textures objectAtIndex:ti]];
[textureNames addObject:[NSNumber numberWithUnsignedInt:tn]];
OOLog(kOOLogShaderInitDumpTexture, @"Shader: initialised texture: %@", [shader_textures objectAtIndex:ti]);
}
GLhandleARB shaderProgram = [TextureStore shaderProgramFromDictionary:shader];
if (shaderProgram)
{
[shader_info setObject:[NSDictionary dictionaryWithObjectsAndKeys:
textureNames, @"textureNames",
[NSValue valueWithPointer:shaderProgram], @"shaderProgram",
[shader objectForKey:@"uniforms"], @"uniforms",
nil]
forKey: shaderKey];
shader = [OOShaderMaterial shaderWithConfiguration:shaderConfig macros:macros bindingTarget:propertyEntity];
if (shader != nil)
{
[materials setObject:shader forKey:shaderKey];
[shader addUniformsFromDictionary:defaultBindings withBindingTarget:propertyEntity];
[shader bindUniform:@"time"
toObject:UNIVERSE
property:@selector(getTime)
clamped:NO];
}
}
}
OOLog(kOOLogShaderInitDumpShaderInfo, @"TESTING: shader_info = %@", shader_info);
OOLogOutdentIf(kOOLogShaderInit);
#endif
}
else
{
if (shader_info)
[shader_info release];
shader_info = nil;
}
OOLogOutdentIf(@"shader.vessel.init");
}
}
- (Entity *)entityForShaderProperties
{
if (!isSubentity) return self;
else return [self owner];
}
- (void) drawEntity:(BOOL) immediate :(BOOL) translucent
{
if (testForShaderSupport)
testForShaders();
NSString *textureKey = nil;
unsigned i;
OOMaterial *material = nil;
NSEnumerator *subEntityEnum = nil;
Entity *subEntity = nil;
if (zero_distance > no_draw_distance) return; // TOO FAR AWAY
if ([UNIVERSE breakPatternHide]) return; // DON'T DRAW
if (cloaking_device_active && (randf() > 0.10)) return; // DON'T DRAW
if (!translucent)
if (no_draw_distance < zero_distance ||
[UNIVERSE breakPatternHide] ||
(cloaking_device_active && randf() > 0.10))
{
if (!shaders_supported)
// Don't draw.
return;
}
NS_DURING
if (!translucent)
{
[super drawEntity:immediate:translucent];
}
else
{
// draw the thing - code take from Entity drawEntity::
//
int ti;
GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_no[] = { 0.0, 0.0, 0.0, 1.0 };
NS_DURING
if (isSmoothShaded)
glShadeModel(GL_SMOOTH);
else
glShadeModel(GL_FLAT);
if (!translucent)
GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_no[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat amb_diff0[] = { 0.5, 0.5, 0.5, 1.0 };
if (EXPECT_NOT(basefile == nil))
{
OOLog(@"render.shipEntity.expectedBaseFile", @"Error: no basefile for entity %@", self);
}
// Set up state
glShadeModel(isSmoothShaded ? GL_SMOOTH : GL_FLAT);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_INDEX_ARRAY);
glDisableClientState(GL_EDGE_FLAG_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer( 3, GL_FLOAT, 0, entityData.vertex_array);
glNormalPointer( GL_FLOAT, 0, entityData.normal_array);
glTexCoordPointer( 2, GL_FLOAT, 0, entityData.texture_uv_array);
if (immediate)
{
/* Gap removal (draw flat polys).
It is my belief that this has absolutely no effect whatsoever on gaps,
as it's using the same geometry as the "real" rendering, but does stop
alpha textures from semi-working. This is probably good, since we
don't depth sort, but could be replaced with disabling blending.
TODO: try the blending thing as above.
-- Ahruman
*/
glDisable(GL_TEXTURE_2D);
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, amb_diff0);
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, mat_no);
glColor4f( 0.25, 0.25, 0.25, 1.0); // gray
glDepthMask(GL_FALSE); // don't write to depth buffer
glDrawArrays(GL_TRIANGLES, 0, entityData.n_triangles); // draw in gray to mask the edges
glDepthMask(GL_TRUE);
// Now draw textured polygons.
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_ambient);
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, mat_no); // TODO: replace with using default OOMaterial if no custom material is defined.
for (i = 1; i <= n_textures; i++)
{
if (basefile)
textureKey = [TextureStore getNameOfTextureWithGLuint: texture_name[i]];
material = [materials objectForKey:textureKey];
if (material == nil)
{
// calls moved here because they are unsupported in display lists
//
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_INDEX_ARRAY);
glDisableClientState(GL_EDGE_FLAG_ARRAY);
//
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer( 3, GL_FLOAT, 0, entityData.vertex_array);
glNormalPointer( GL_FLOAT, 0, entityData.normal_array);
glTexCoordPointer( 2, GL_FLOAT, 0, entityData.texture_uv_array);
ShipEntity *propertyEntity;
if (!isSubentity) propertyEntity = self;
else propertyEntity = (ShipEntity *)[self owner];
GLfloat utime = (GLfloat)[UNIVERSE getTime];
GLfloat engine_level = [propertyEntity speed_factor];
GLfloat laser_heat_level = [propertyEntity laserHeatLevel];
GLfloat hull_heat_level = [propertyEntity hullHeatLevel];
int entity_personality_int = propertyEntity->entity_personality;
laser_heat_level = OOClamp_0_1_f(laser_heat_level);
if (immediate)
{
//
// gap removal (draws flat polys)
//
glDisable(GL_TEXTURE_2D);
GLfloat amb_diff0[] = { 0.5, 0.5, 0.5, 1.0};
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, amb_diff0);
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, mat_no);
glColor4f( 0.25, 0.25, 0.25, 1.0); // gray
glDepthMask(GL_FALSE); // don't write to depth buffer
glDrawArrays( GL_TRIANGLES, 0, entityData.n_triangles); // draw in gray to mask the edges
glDepthMask(GL_TRUE);
//
// now the textures ...
//
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_ambient);
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, mat_no);
for (ti = 1; ti <= n_textures; ti++)
{
NSString* textureKey = [TextureStore getNameOfTextureWithGLuint: texture_name[ti]];
#ifndef NO_SHADERS
if ((shader_info) && [shader_info objectForKey: textureKey])
{
NSDictionary *shader = [shader_info objectForKey:textureKey];
GLhandleARB shaderProgram = [[shader objectForKey:@"shaderProgram"] pointerValue];
GLint variable_location;
//
// set up texture units
//
glUseProgramObjectARB(shaderProgram);
//
NSArray *texture_units = [shader objectForKey:@"textureNames"];
int n_tu = [texture_units count];
int i;
for (i = 0; i < n_tu; i++)
{
// set up each texture unit in turn
// associating texN with each texture
GLuint textureN = [[texture_units objectAtIndex:i] intValue];
glActiveTextureARB( GL_TEXTURE0_ARB + i);
glBindTexture( GL_TEXTURE_2D, textureN);
NSString* texdname = [NSString stringWithFormat:@"tex%d", i];
const char* cname = [texdname UTF8String];
variable_location = glGetUniformLocationARB(shaderProgram, cname);
if (variable_location == -1)
OOLog(kOOLogShaderTextureNameMissing, @"GLSL ERROR couldn't find location of %@ in shaderProgram %d", texdname, shaderProgram);
else
glUniform1iARB(variable_location, i); // associate texture unit number i with tex%d
}
NSDictionary *uniforms = [shader objectForKey:@"uniforms"];
if (uniforms != nil)
{
ApplyConstantUniforms([shader objectForKey:@"uniforms"], shaderProgram);
}
// other uniform variables
variable_location = glGetUniformLocationARB( shaderProgram, "time");
if (variable_location != -1)
{
OOLog(@"rendering.opengl.shader.uniform.time", @"Binding time: %g", time);
glUniform1fARB(variable_location, utime);
}
variable_location = glGetUniformLocationARB( shaderProgram, "engine_level");
if (variable_location != -1)
{
OOLog(@"rendering.opengl.shader.uniform.engineLevel", @"Binding engine_level: %g", engine_level);
glUniform1fARB(variable_location, engine_level);
}
variable_location = glGetUniformLocationARB( shaderProgram, "laser_heat_level");
if (variable_location != -1)
{
OOLog(@"rendering.opengl.shader.uniform.laserHeatLevel", @"Binding laser_heat_level: %g", laser_heat_level);
glUniform1fARB(variable_location, laser_heat_level);
}
variable_location = glGetUniformLocationARB( shaderProgram, "hull_heat_level");
if (variable_location != -1)
{
OOLog(@"rendering.opengl.shader.uniform.hullHeatLevel", @"Binding hull_heat_level: %g", hull_heat_level);
glUniform1fARB(variable_location, hull_heat_level);
}
variable_location = glGetUniformLocationARB( shaderProgram, "entity_personality_int");
if (variable_location != -1)
{
OOLog(@"rendering.opengl.shader.uniform.entityPersonality.int", @"Binding entity_personality_int: %i", entity_personality_int);
glUniform1iARB(variable_location, entity_personality_int);
}
variable_location = glGetUniformLocationARB( shaderProgram, "entity_personality");
if (variable_location != -1)
{
OOLog(@"rendering.opengl.shader.uniform.entityPersonality.float", @"Binding entity_personality: %g", entity_personality_int / (float)0x7FFF);
glUniform1fARB(variable_location, entity_personality_int / (float)0x7FFF);
}
}
else
#endif
glBindTexture(GL_TEXTURE_2D, texture_name[ti]);
glDrawArrays( GL_TRIANGLES, triangle_range[ti].location, triangle_range[ti].length);
#ifndef NO_SHADERS
// switch off shader
if ((shader_info) && [shader_info objectForKey: textureKey])
{
glUseProgramObjectARB(0);
glActiveTextureARB( GL_TEXTURE0_ARB);
}
#endif
}
}
else
{
if (displayListName != 0)
{
[self drawEntity: YES : translucent];
}
else
{
[self initialiseTextures];
#ifdef GNUSTEP
// TODO: Find out what these APPLE functions can be replaced with
#else
if (usingVAR)
glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#endif
[self generateDisplayList];
}
}
// TODO: use a default material instead
[OOMaterial applyNone];
glBindTexture(GL_TEXTURE_2D, texture_name[i]);
}
else
{
OOLog(kOOLogFileNotFound, @"ERROR no basefile for entity %@");
[material apply];
}
glDrawArrays( GL_TRIANGLES, triangle_range[i].location, triangle_range[i].length);
}
[OOMaterial applyNone];
}
else
{
// Not immediate.
if (displayListName != 0)
{
// TODO: Isn't this equivalent to "if immedate || displayListName != 0" above, along with passing displayListName != 0 as the super call's immediate parameter? -- Ahruman
[self drawEntity:YES :translucent];
}
glShadeModel(GL_SMOOTH);
CheckOpenGLErrors([NSString stringWithFormat:@"Entity after drawing %@", self]);
NS_HANDLER
OOLog(kOOLogException, @"***** [Entity drawEntity::] encountered exception: %@ : %@ *****",[localException name], [localException reason]);
OOLog(kOOLogException, @"***** Removing entity %@ from UNIVERSE *****", self);
[UNIVERSE removeEntity:self];
if ([[localException name] hasPrefix:@"Oolite"])
[UNIVERSE handleOoliteException:localException]; // handle these ourself
else
[localException raise]; // pass these on
NS_ENDHANDLER
{
// Set up display list.
[self initialiseTextures];
#if GL_APPLE_vertex_array_object
if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#endif
[self generateDisplayList];
}
}
if (!isSmoothShaded) glShadeModel(GL_SMOOTH);
}
}
else
{
if ((status == STATUS_COCKPIT_DISPLAY)&&((debug | debug_flag) & (DEBUG_COLLISIONS | DEBUG_OCTREE)))
[octree drawOctree];
if ((debug | debug_flag) & (DEBUG_COLLISIONS | DEBUG_OCTREE))
[octree drawOctreeCollisions];
if ((isSubentity)&&[self owner])
else
{
if (([self owner]->status == STATUS_COCKPIT_DISPLAY)&&((debug | debug_flag) & (DEBUG_COLLISIONS | DEBUG_OCTREE)))
// Translucent.
if ((status == STATUS_COCKPIT_DISPLAY)&&((debug | debug_flag) & (DEBUG_COLLISIONS | DEBUG_OCTREE)))
[octree drawOctree];
if ((debug | debug_flag) & (DEBUG_COLLISIONS | DEBUG_OCTREE))
[octree drawOctreeCollisions];
if ((isSubentity)&&[self owner])
{
if (([self owner]->status == STATUS_COCKPIT_DISPLAY)&&((debug | debug_flag) & (DEBUG_COLLISIONS | DEBUG_OCTREE)))
[octree drawOctree];
if ((debug | debug_flag) & (DEBUG_COLLISIONS | DEBUG_OCTREE))
[octree drawOctreeCollisions];
}
}
}
//
CheckOpenGLErrors([NSString stringWithFormat:@"ShipEntity after drawing Entity (main) %@", self]);
//
if (immediate)
return; // don't draw sub-entities when constructing a displayList
if (sub_entities)
{
int i;
for (i = 0; i < [sub_entities count]; i++)
if (!immediate)
{
Entity *se = (Entity *)[sub_entities objectAtIndex:i];
[se setOwner:self]; // refresh ownership
[se drawSubEntity:immediate:translucent];
// Draw subentities.
for (subEntityEnum = [sub_entities objectEnumerator]; (subEntity = [subEntityEnum nextObject]); )
{
[subEntity setOwner:self]; // refresh ownership
[subEntity drawSubEntity:immediate :translucent];
}
}
}
//
CheckOpenGLErrors([NSString stringWithFormat:@"ShipEntity after drawing Entity (subentities) %@", self]);
//
CheckOpenGLErrors([NSString stringWithFormat:@"%s after drawing %@ (immediate: %s, translucent: %s)", __PRETTY_FUNCTION__, self, immediate ? "YES" : "NO", translucent ? "YES" : "NO"]);
NS_HANDLER
OOLog(@"exception.shipEntity.draw", @"***** %s encountered exception: %@ : %@ *****", __PRETTY_FUNCTION__, [localException name], [localException reason]);
OOLog(@"exception.shipEntity.draw", @"***** Removing entity %@ from UNIVERSE *****", self);
[UNIVERSE removeEntity:self];
if ([[localException name] hasPrefix:@"Oolite"]) [UNIVERSE handleOoliteException:localException]; // handle these ourself
else [localException raise]; // pass these on
NS_ENDHANDLER
}
- (void) drawSubEntity:(BOOL) immediate :(BOOL) translucent
{
Entity* my_owner = [UNIVERSE entityForUniversalID:owner];
@ -3821,10 +3722,9 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
return max_flight_speed;
}
- (GLfloat) speed_factor
- (GLfloat) speedFactor
{
if (max_flight_speed <= 0.0)
return 0.0;
if (max_flight_speed <= 0.0) return 0.0;
return flight_speed / max_flight_speed;
}
@ -4495,18 +4395,31 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
}
- (GLfloat)laserHeatLevel
- (float)laserHeatLevel
{
return (weapon_recharge_rate - shot_time) / weapon_recharge_rate;
float result = (weapon_recharge_rate - shot_time) / weapon_recharge_rate;
return result;
}
- (GLfloat)hullHeatLevel
- (float)hullHeatLevel
{
return ship_temperature / (GLfloat)SHIP_MAX_CABIN_TEMP;
}
- (float)entityPersonality
{
return entity_personality / (float)0x7FFF;
}
- (int)entityPersonalityInt
{
return entity_personality;
}
- (void)setSuppressExplosion:(BOOL)suppress
{
suppressExplosion = suppress != NO;
@ -7679,7 +7592,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role)
flagsString = [flags count] ? [flags componentsJoinedByString:@", "] : @"none";
OOLog(@"dumpState.shipEntity", @"Flags: %@", flagsString);
OOLog(@"dumpState.shipEntity.glsl", @"engine_level: %g", [self speed_factor]);
OOLog(@"dumpState.shipEntity.glsl", @"engine_level: %g", [self speedFactor]);
OOLog(@"dumpState.shipEntity.glsl", @"laser_heat_level: %g", OOClamp_0_1_f([self laserHeatLevel]));
OOLog(@"dumpState.shipEntity.glsl", @"hull_heat_level: %g", [self hullHeatLevel]);
OOLog(@"dumpState.shipEntity.glsl", @"entity_personality: %g", entity_personality / (float)0x7FFF);
@ -7717,6 +7630,7 @@ static NSString * const kOOCacheOctrees = @"octrees";
@end
#if OLD_SHADERS
// This could be more efficient.
static void ApplyConstantUniforms(NSDictionary *uniforms, GLhandleARB shaderProgram)
{
@ -7770,4 +7684,5 @@ static void ApplyConstantUniforms(NSDictionary *uniforms, GLhandleARB shaderProg
}
}
}
}
}
#endif

View File

@ -478,9 +478,8 @@ MA 02110-1301, USA.
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#ifdef GNUSTEP
// TODO: find replacement for APPLE function
#else
#if GL_APPLE_vertex_array_object
if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]);
#endif
glBindTexture(GL_TEXTURE_2D, star_textureName);
@ -517,9 +516,8 @@ MA 02110-1301, USA.
if (![UNIVERSE reducedDetail])
{
glBindTexture(GL_TEXTURE_2D, blob_textureName);
#ifdef GNUSTEP
// TODO: Find replacement for APPLE fncall
#else
#if GL_APPLE_vertex_array_object
if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[1]);
#endif

View File

@ -48,10 +48,6 @@ extern int debug;
+ (NSString*) getNameOfTextureWithGLuint:(GLuint) value;
+ (NSSize) getSizeOfTexture:(NSString *)filename;
#ifndef NO_SHADERS
+ (GLhandleARB) shaderProgramFromDictionary:(NSDictionary *) shaderDict;
#endif
+ (void) reloadTextures;

View File

@ -38,11 +38,6 @@ MA 02110-1301, USA.
static NSString * const kOOLogPlanetTextureGen = @"texture.planet.generate";
static NSString * const kOOLogShaderInitSuccess = @"rendering.opengl.shader.init.success";
static NSString * const kOOLogShaderInitFailed = @"rendering.opengl.shader.init.failed";
static BOOL GetShaderSource(NSString *shaderType, NSDictionary *shaderDict, NSString **outResult);
@implementation TextureStore
@ -318,172 +313,11 @@ GLuint max_texture_dimension = 512; // conservative start
return size;
}
#ifndef NO_SHADERS
+ (GLhandleARB) shaderProgramFromDictionary:(NSDictionary *) shaderDict
{
if ([shaderUniversalDictionary objectForKey:shaderDict])
return (GLhandleARB)[(NSNumber*)[shaderUniversalDictionary objectForKey:shaderDict] unsignedIntValue];
if (!shaderDict)
{
NSLog(@"ERROR: null dictionary passed to [TextureStore prepareShaderFDromDictionary:]");
return NULL_SHADER; // failed!
}
GLhandleARB fragment_shader_object = NULL_SHADER;
GLhandleARB vertex_shader_object = NULL_SHADER;
GLhandleARB shader_program = NULL_SHADER;
NSString *fragmentSource = nil;
NSString *vertexSource = nil;
BOOL OK = YES;
NSString *shaderEnvMacros =
@"#define OO_TIME\t\t\t\t\t\t1\n"
"#define OO_ENGINE_LEVEL\t\t\t\t1\n"
"#define OO_LASER_HEAT_LEVEL\t\t\t1\n"
"#define OO_HULL_HEAT_LEVEL\t\t\t1\n"
"#define OO_HULL_HEAT_LEVEL\t\t\t1\n"
"#define OO_ENTITY_PERSONALITY_INT\t1\n"
"#define OO_ENTITY_PERSONALITY\t\t1\n"
"\n";
if (!GetShaderSource(@"fragment", shaderDict, &fragmentSource)) return NULL_SHADER;
if (fragmentSource == nil) fragmentSource = [shaderDict objectForKey:@"glsl"];
if (!GetShaderSource(@"vertex", shaderDict, &vertexSource)) return NULL_SHADER;
if (fragmentSource == nil && vertexSource == nil)
{
OOLog(kOOLogShaderInitFailed, @"Shader dictionary specifies neither vertex shader nor fragment shader:\n", shaderDict);
return NULL_SHADER;
}
// check if we need to make a fragment shader
if (fragmentSource != nil)
{
GLhandleARB shader_object = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); // a fragment shader
if (!shader_object)
{
OOLog(kOOLogShaderInitFailed, @"GLSL ERROR: could not create a fragment shader with glCreateShaderObjectARB()");
OK = NO;
}
if (OK)
{
fragmentSource = [shaderEnvMacros stringByAppendingString:fragmentSource];
const GLcharARB *fragment_string;
fragment_string = [fragmentSource cString];
glShaderSourceARB(shader_object, 1, &fragment_string, NULL);
// compile the shader!
glCompileShaderARB(shader_object);
GLint result;
glGetObjectParameterivARB(shader_object, GL_OBJECT_COMPILE_STATUS_ARB, &result);
if (result != GL_TRUE)
{
char log[1024];
GLsizei log_length;
glGetInfoLogARB( shader_object, 1024, &log_length, log);
OOLog(kOOLogShaderInitFailed, @"GLSL ERROR: shader code would not compile:\n%s\n\n%@\n\n", log, fragmentSource);
OK = NO;
}
fragment_shader_object = shader_object;
}
}
// check if we need to make a vertex shader
if (vertexSource)
{
GLhandleARB shader_object = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); // a vertex shader
if (!shader_object)
{
OOLog(kOOLogShaderInitFailed, @"GLSL ERROR: could not create a fragment shader with glCreateShaderObjectARB()");
OK = NO;
}
if (OK)
{
vertexSource = [shaderEnvMacros stringByAppendingString:vertexSource];
const GLcharARB *vertex_string;
vertex_string = [vertexSource cString];
glShaderSourceARB(shader_object, 1, &vertex_string, NULL);
// compile the shader!
glCompileShaderARB(shader_object);
GLint result;
glGetObjectParameterivARB(shader_object, GL_OBJECT_COMPILE_STATUS_ARB, &result);
if (result != GL_TRUE)
{
char log[1024];
GLsizei log_length;
glGetInfoLogARB( shader_object, 1024, &log_length, log);
OOLog(kOOLogShaderInitFailed, @"GLSL ERROR: shader code would not compile:\n%s\n\n%@\n\n", log, vertexSource);
OK = NO;
}
vertex_shader_object = shader_object;
}
}
if (OK && !fragment_shader_object && !vertex_shader_object)
{
OOLog(kOOLogShaderInitFailed, @"GLSL ERROR: could not create any shaders from %@", shaderDict);
OK = NO;
}
// create a shader program
if (OK)
{
shader_program = glCreateProgramObjectARB();
if (!shader_program)
{
OOLog(kOOLogShaderInitFailed, @"GLSL ERROR: could not create a shader program with glCreateProgramObjectARB()");
OK = NO;
}
}
if (OK)
{
// attach the shader objects
if (vertex_shader_object) glAttachObjectARB(shader_program, vertex_shader_object);
if (fragment_shader_object) glAttachObjectARB(shader_program, fragment_shader_object);
// link the program
glLinkProgramARB(shader_program);
GLint result;
glGetObjectParameterivARB(shader_program, GL_OBJECT_LINK_STATUS_ARB, &result);
if (result != GL_TRUE)
{
char log[1024];
GLsizei log_length;
glGetInfoLogARB(shader_program, 1024, &log_length, log);
OOLog(kOOLogShaderInitFailed, @"GLSL ERROR: shader program would not link:\n%s\n\n%@\n\n", log, shaderDict);
OK = NO;
}
}
if (vertex_shader_object != NULL_SHADER) glDeleteObjectARB(vertex_shader_object);
if (fragment_shader_object != NULL_SHADER) glDeleteObjectARB(fragment_shader_object);
if (!OK && shader_program != NULL_SHADER) glDeleteObjectARB(shader_program);
if (OK)
{
// store the resulting program for reuse
if (!shaderUniversalDictionary) shaderUniversalDictionary = [[NSMutableDictionary dictionary] retain];
[shaderUniversalDictionary setObject: [NSNumber numberWithUnsignedInt: (unsigned int) shader_program] forKey: shaderDict];
}
return OK ? shader_program : NULL_SHADER;
}
#endif
+ (void) reloadTextures
{
/*
FIX_ME: This function is only called when switching between strict and
FIXME: This function is only called when switching between strict and
non-strict mode, and apparently under some circumstances under GNUstep.
It's so old that the dictionary it works on is used for almost exactly
the opposite of what it expects. This is why we use classes and
@ -943,52 +777,3 @@ void fillSquareImageWithPlanetNMap(unsigned char * imageBuffer, int width, int n
}
@end
/* Attempt to load fragment or vertex shader source.
Returns YES if source was loaded or no shader was specified, and NO if an
external shader was specified but could not be found.
*/
static BOOL GetShaderSource(NSString *shaderType, NSDictionary *shaderDict, NSString **outResult)
{
NSString *result = nil;
NSString *shaderName = nil;
NSArray *extensions = nil;
NSEnumerator *extEnum = nil;
NSString *extension = nil;
NSString *nameWithExtension = nil;
shaderName = [shaderDict objectForKey:[shaderType stringByAppendingString:@"_shader"]];
if (shaderName != nil)
{
result = [ResourceManager stringFromFilesNamed:shaderName inFolder:@"Shaders"];
if (result == nil)
{
extensions = [NSArray arrayWithObjects:shaderType, [shaderType substringToIndex:4], nil]; // vertex and vert, or fragment and frag
// Futureproofing -- in future, we may wish to support automatic selection between supported shader languages.
if (![shaderName pathHasExtensionInArray:extensions])
{
for (extEnum = [extensions objectEnumerator]; (extension = [extEnum nextObject]); )
{
nameWithExtension = [shaderName stringByAppendingPathExtension:extension];
result = [ResourceManager stringFromFilesNamed:nameWithExtension
inFolder:@"Shaders"];
if (result != nil) break;
}
}
if (result == nil)
{
OOLog(kOOLogFileNotFound, @"GLSL ERROR: failed to find fragment program %@.", shaderName);
return NO;
}
}
}
else
{
result = [shaderDict objectForKey:[@"glsl-" stringByAppendingString:shaderType]];
}
if (outResult != NULL) *outResult = result;
return YES;
}

View File

@ -29,6 +29,7 @@ MA 02110-1301, USA.
#import "legacy_random.h"
#import "OOMaths.h"
#import "OOColor.h"
#import "OOWeakReference.h"
#define CROSSHAIR_SIZE 32.0
@ -108,126 +109,128 @@ MA 02110-1301, USA.
extern int debug;
@interface Universe : NSObject
@interface Universe: NSObject <OOWeakReferenceSupport>
{
@public
// use a sorted list for drawing and other activities
//
Entity* sortedEntities[UNIVERSE_MAX_ENTITIES];
int n_entities;
int cursor_row;
@public
// use a sorted list for drawing and other activities
//
Entity* sortedEntities[UNIVERSE_MAX_ENTITIES];
int n_entities;
int cursor_row;
// // collision optimisation sorted lists
Entity *x_list_start, *y_list_start, *z_list_start;
Entity *x_list_start, *y_list_start, *z_list_start;
// //
// ////
// colors
//
GLfloat sun_diffuse[4];
GLfloat sun_specular[4];
GLfloat stars_ambient[4];
GLfloat air_resist_factor;
int viewDirection; // read only
@protected
MyOpenGLView *gameView;
#ifndef GNUSTEP
NSSpeechSynthesizer* speechSynthesizer; // use this from OS X 10.3 onwards
NSArray *speechArray;
#endif
int next_universal_id;
Entity* entity_for_uid[MAX_ENTITY_UID];
// colors
//
GLfloat sun_diffuse[4];
GLfloat sun_specular[4];
GLfloat stars_ambient[4];
GLfloat air_resist_factor;
NSMutableArray *entities;
int station;
int sun;
int planet;
int firstBeacon, lastBeacon;
GLfloat sky_clear_color[4];
NSString *currentMessage;
GuiDisplayGen* gui;
GuiDisplayGen* message_gui;
GuiDisplayGen* comm_log_gui;
BOOL displayGUI;
BOOL displayCursor;
BOOL reducedDetail;
BOOL displayFPS;
double universal_time;
double time_delta;
double ai_think_time;
double demo_stage_time;
int demo_stage;
int demo_ship_index;
NSArray *demo_ships;
GLfloat sun_center_position[4];
BOOL dumpCollisionInfo;
NSDictionary *shipdata; // holds data on all ships available, loaded at initialisation
NSDictionary *shipyard; // holds data on all ships for sale, loaded at initialisation
NSDictionary *commoditylists; // holds data on commodities for various types of station, loaded at initialisation
NSArray *commoditydata; // holds data on commodities extracted from commoditylists
NSDictionary *illegal_goods; // holds the legal penalty for illicit commodities, loaded at initialisation
NSDictionary *descriptions; // holds descriptive text for lots of stuff, loaded at initialisation
NSDictionary *customsounds; // holds descriptive audio for lots of stuff, loaded at initialisation
NSDictionary *characters; // holds descriptons of characters
NSDictionary *planetinfo; // holds overrides for individual planets, keyed by "g# p#" where g# is the galaxy number 0..7 and p# the planet number 0..255
NSDictionary *missiontext; // holds descriptive text for missions, loaded at initialisation
NSArray *equipmentdata; // holds data on available equipment, loaded at initialisation
Random_Seed galaxy_seed;
Random_Seed system_seed;
Random_Seed target_system_seed;
Random_Seed systems[256]; // hold pregenerated universe info
NSString* system_names[256]; // hold pregenerated universe info
BOOL system_found[256]; // holds matches for input strings
int breakPatternCounter;
ShipEntity *demo_ship;
StationEntity* cachedStation;
PlanetEntity* cachedPlanet;
PlanetEntity* cachedSun;
BOOL strict;
BOOL no_update;
NSMutableDictionary* local_planetinfo_overrides;
NSException* exception;
NSMutableArray* activeWormholes;
NSMutableArray* characterPool;
CollisionRegion* universeRegion;
// check and maintain linked lists occasionally
BOOL doLinkedListMaintenanceThisUpdate;
// experimental proc-genned textures
BOOL doProcedurallyTexturedPlanets;
int viewDirection; // read only
@protected
MyOpenGLView *gameView;
#ifndef GNUSTEP
NSSpeechSynthesizer* speechSynthesizer; // use this from OS X 10.3 onwards
NSArray *speechArray;
#endif
int next_universal_id;
Entity* entity_for_uid[MAX_ENTITY_UID];
NSMutableArray *entities;
int station;
int sun;
int planet;
int firstBeacon, lastBeacon;
GLfloat sky_clear_color[4];
NSString *currentMessage;
GuiDisplayGen* gui;
GuiDisplayGen* message_gui;
GuiDisplayGen* comm_log_gui;
BOOL displayGUI;
BOOL displayCursor;
BOOL reducedDetail;
BOOL displayFPS;
double universal_time;
double time_delta;
double ai_think_time;
double demo_stage_time;
int demo_stage;
int demo_ship_index;
NSArray *demo_ships;
GLfloat sun_center_position[4];
BOOL dumpCollisionInfo;
NSDictionary *shipdata; // holds data on all ships available, loaded at initialisation
NSDictionary *shipyard; // holds data on all ships for sale, loaded at initialisation
NSDictionary *commoditylists; // holds data on commodities for various types of station, loaded at initialisation
NSArray *commoditydata; // holds data on commodities extracted from commoditylists
NSDictionary *illegal_goods; // holds the legal penalty for illicit commodities, loaded at initialisation
NSDictionary *descriptions; // holds descriptive text for lots of stuff, loaded at initialisation
NSDictionary *customsounds; // holds descriptive audio for lots of stuff, loaded at initialisation
NSDictionary *characters; // holds descriptons of characters
NSDictionary *planetinfo; // holds overrides for individual planets, keyed by "g# p#" where g# is the galaxy number 0..7 and p# the planet number 0..255
NSDictionary *missiontext; // holds descriptive text for missions, loaded at initialisation
NSArray *equipmentdata; // holds data on available equipment, loaded at initialisation
Random_Seed galaxy_seed;
Random_Seed system_seed;
Random_Seed target_system_seed;
Random_Seed systems[256]; // hold pregenerated universe info
NSString* system_names[256]; // hold pregenerated universe info
BOOL system_found[256]; // holds matches for input strings
int breakPatternCounter;
ShipEntity *demo_ship;
StationEntity* cachedStation;
PlanetEntity* cachedPlanet;
PlanetEntity* cachedSun;
BOOL strict;
BOOL no_update;
NSMutableDictionary* local_planetinfo_overrides;
NSException* exception;
NSMutableArray* activeWormholes;
NSMutableArray* characterPool;
CollisionRegion* universeRegion;
// check and maintain linked lists occasionally
BOOL doLinkedListMaintenanceThisUpdate;
// experimental proc-genned textures
BOOL doProcedurallyTexturedPlanets;
OOWeakReference *weakSelf;
}
- (BOOL) doProcedurallyTexturedPlanets;

View File

@ -276,9 +276,25 @@ static BOOL MaintainLinkedLists(Universe* uni);
[[OOCacheManager sharedCache] flush];
[weakSelf weakRefDrop];
[super dealloc];
}
- (id)weakRetain
{
if (weakSelf == nil) weakSelf = [OOWeakReference weakRefWithObject:self];
return [weakSelf retain];
}
- (void)weakRefDied:(OOWeakReference *)weakRef
{
if (weakRef == weakSelf) weakSelf = nil;
}
- (BOOL) doProcedurallyTexturedPlanets
{
return doProcedurallyTexturedPlanets;