Support loading of shaders from external file. New uniform variable, hull_heat_level. Fixed leak when shader loading fails.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@867 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2007-03-22 20:33:04 +00:00
parent ce75bbe608
commit b30d3692cf
5 changed files with 219 additions and 194 deletions

View File

@ -124,7 +124,7 @@ mesh.load.error.tooManyVertices = inherit;
mesh.load.error.tooManyFaces = inherit;
$plistError = $error;
$plistError = $error;
plist.parse.foundation.failed = $plistError;
plist.wrongType = $plistError;
plist.homebrew.badEncoding = $plistError;
@ -136,6 +136,7 @@ plist.homebrew.interpret.trace = no; // Log details of second stage of hom
plist.homebrew.success = yes;
$shaderError = $scriptError;
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
@ -146,7 +147,8 @@ 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 = $scriptError;
rendering.opengl.shader.init.failed = $shaderError;
rendering.opengl.shader.texNameMissing = $shaderError;
rendering.opengl.stateDump = $troubleShootingDump; // Dump of OpenGL state (debug tool, currently unused)

View File

@ -122,22 +122,26 @@ id OOPropertyListFromFile(NSString *path)
*/
static NSData *CopyDataFromFile(NSString *path)
{
NSFileManager *fmgr = [NSFileManager defaultManager];
BOOL dir;
if ([fmgr fileExistsAtPath:path isDirectory:&dir])
{
if (!dir)
#ifdef GNUSTEP
NSFileManager *fmgr = [NSFileManager defaultManager];
BOOL dir;
if ([fmgr fileExistsAtPath:path isDirectory:&dir])
{
return [[NSData alloc] initWithContentsOfMappedFile:path];
if (!dir)
{
return [[NSData alloc] initWithContentsOfMappedFile:path];
}
else
{
OOLog(kOOLogFileNotFound, @"Expected property list but found directory at %@", path);
}
}
else
{
OOLog(kOOLogFileNotFound, @"Expected property list but found directory at %@", path);
}
}
return nil;
return nil;
#else
return [[NSData alloc] initWithContentsOfMappedFile:path];
#endif
}

View File

@ -62,11 +62,11 @@ BOOL always_include_addons;
#ifndef GNUSTEP
+ (NSImage *) imageNamed:(NSString *)filename inFolder:(NSString *)foldername;
#endif
+ (NSString *) stringFromFilesNamed:(NSString *)filename inFolder:(NSString *)foldername;
#ifdef GNUSTEP
#else
+ (SDLImage *) surfaceNamed:(NSString *)filename inFolder:(NSString *)foldername;
#endif
+ (NSString *) stringFromFilesNamed:(NSString *)filename inFolder:(NSString *)foldername;
+ (NSDictionary *) loadScripts;
@end

View File

@ -58,8 +58,7 @@ 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 kOOLogShaderInitSuccess = @"rendering.opengl.shader.init.success";
static NSString * const kOOLogShaderInitFailed = @"rendering.opengl.shader.init.failed";
static NSString * const kOOLogShaderTextureNameMissing = @"rendering.opengl.shader.texNameMissing";
#ifdef GNUSTEP
void loadOpenGLFunctions()
@ -697,12 +696,9 @@ NSString* describeStatus(int some_status)
//
group_id = NO_TARGET;
//
if (launch_actions)
[launch_actions removeAllObjects];
if (script_actions)
[script_actions removeAllObjects];
if (death_actions)
[death_actions removeAllObjects];
[launch_actions removeAllObjects];
[script_actions removeAllObjects];
[death_actions removeAllObjects];
//
last_escort_target = NO_TARGET;
n_escorts = 0;
@ -764,8 +760,7 @@ NSString* describeStatus(int some_status)
behaviour = BEHAVIOUR_IDLE;
frustration = 0.0;
//
if (shipAI)
[shipAI autorelease];
[shipAI autorelease];
shipAI = [[AI alloc] init]; // alloc retains
[shipAI setOwner:self];
[shipAI setState:@"GLOBAL"];
@ -784,16 +779,15 @@ NSString* describeStatus(int some_status)
//
reportAImessages = NO;
//
if (previousCondition) [previousCondition autorelease];
[previousCondition autorelease];
previousCondition = nil;
//
if (sub_entities) [sub_entities autorelease];
[sub_entities autorelease];
sub_entities = nil;
//
scanner_range = 25600.0;
//
if (shipinfoDictionary)
[shipinfoDictionary autorelease];
[shipinfoDictionary autorelease];
shipinfoDictionary = nil;
//
being_fined = NO;
@ -817,20 +811,17 @@ NSString* describeStatus(int some_status)
isFrangible = YES;
subentity_taking_damage = nil;
//
if (dockingInstructions)
[dockingInstructions autorelease];
[dockingInstructions autorelease];
dockingInstructions = nil;
//
if (crew)
[crew autorelease];
[crew autorelease];
crew = nil;
//
[self setTrackCloseContacts:NO];
//
isNearPlanetSurface = NO;
//
if (lastRadioMessage)
[lastRadioMessage autorelease];
[lastRadioMessage autorelease];
lastRadioMessage = nil;
//
tractor_position = make_vector( 0.0f, 0.0f, 0.0f);
@ -847,11 +838,8 @@ NSString* describeStatus(int some_status)
//
[self setBrain: nil];
//
if (shader_info)
{
[shader_info release];
shader_info = nil;
}
[shader_info release];
shader_info = nil;
}
@ -3376,12 +3364,13 @@ void testForShaders()
// GLuint shader_program = [TextureStore shaderProgramFromDictionary: shader];
GLhandleARB shader_program = [TextureStore shaderProgramFromDictionary: shader];
if (shader_program)
OOLog(kOOLogShaderInitSuccess, @"Successfully compiled shader program is %d", shader_program);
else
OOLog(kOOLogShaderInitFailed, @"***** Failed to initialise shader program!");
[shader_info setObject:[NSDictionary dictionaryWithObjectsAndKeys:
textureNames, @"textureNames", [NSNumber numberWithUnsignedInt: (unsigned int) shader_program], @"shader_program", nil]
forKey: shader_key];
{
[shader_info setObject:[NSDictionary dictionaryWithObjectsAndKeys:
textureNames, @"textureNames",
[NSNumber numberWithUnsignedInt:(unsigned)shader_program], @"shader_program",
nil]
forKey: shader_key];
}
}
OOLog(kOOLogShaderInitDumpShaderInfo, @"TESTING: shader_info = %@", shader_info);
@ -3448,8 +3437,9 @@ void testForShaders()
GLfloat utime = (GLfloat)[universe getTime];
GLfloat engine_level = (max_flight_speed > 0.0f)? flight_speed / max_flight_speed : 0.0f;
GLfloat engine_level = [self speed_factor];
GLfloat laser_heat_level = (isPlayer)? [(PlayerEntity*)self dial_weapon_temp]: (weapon_recharge_rate - shot_time) / weapon_recharge_rate;
GLfloat hull_heat_level = (isPlayer)? [(PlayerEntity*)self dial_ship_temperature]: ship_temperature / (GLfloat)SHIP_MAX_CABIN_TEMP;
if (immediate)
@ -3480,15 +3470,15 @@ void testForShaders()
#ifndef NO_SHADERS
if ((shader_info) && [shader_info objectForKey: textureKey])
{
NSDictionary* shader = (NSDictionary*)[shader_info objectForKey:textureKey];
GLhandleARB shader_program = (GLhandleARB)[(NSNumber*)[shader objectForKey:@"shader_program"] unsignedIntValue];
NSDictionary *shader = (NSDictionary*)[shader_info objectForKey:textureKey];
GLhandleARB shader_program = (GLhandleARB)[(NSNumber*)[shader objectForKey:@"shader_program"] unsignedIntValue];
GLint variable_location;
//
// set up texture units
//
glUseProgramObjectARB( shader_program);
glUseProgramObjectARB(shader_program);
//
NSArray* texture_units = (NSArray*)[shader objectForKey:@"textureNames"];
NSArray *texture_units = [shader objectForKey:@"textureNames"];
int n_tu = [texture_units count];
int i;
for (i = 0; i < n_tu; i++)
@ -3502,27 +3492,29 @@ void testForShaders()
NSString* texdname = [NSString stringWithFormat:@"tex%d", i];
const char* cname = [texdname UTF8String];
GLint locator = glGetUniformLocationARB( shader_program, cname);
if (locator == -1)
NSLog(@"GLSL ERROR couldn't find location of %@ in shader_program %d", texdname, shader_program);
variable_location = glGetUniformLocationARB(shader_program, cname);
if (variable_location == -1)
OOLog(kOOLogShaderTextureNameMissing, @"GLSL ERROR couldn't find location of %@ in shader_program %d", texdname, shader_program);
else
glUniform1iARB( locator, i); // associate texture unit number i with tex%d
glUniform1iARB(variable_location, i); // associate texture unit number i with tex%d
}
//
// other variables 'time' 'engine_level'
//
GLint time_location = glGetUniformLocationARB( shader_program, "time");
if (time_location != -1)
glUniform1fARB( time_location, utime);
//
GLint engine_level_location = glGetUniformLocationARB( shader_program, "engine_level");
if (engine_level_location != -1)
glUniform1fARB( engine_level_location, engine_level);
//
GLint laser_heat_level_location = glGetUniformLocationARB( shader_program, "laser_heat_level");
if (laser_heat_level_location != -1)
glUniform1fARB( laser_heat_level_location, laser_heat_level);
//
variable_location = glGetUniformLocationARB( shader_program, "time");
if (variable_location != -1)
glUniform1fARB(variable_location, utime);
variable_location = glGetUniformLocationARB( shader_program, "engine_level");
if (variable_location != -1)
glUniform1fARB(variable_location, engine_level);
variable_location = glGetUniformLocationARB( shader_program, "laser_heat_level");
if (variable_location != -1)
glUniform1fARB(variable_location, laser_heat_level);
variable_location = glGetUniformLocationARB( shader_program, "hull_heat_level");
if (variable_location != -1)
glUniform1fARB(variable_location, hull_heat_level);
}
else
#endif

View File

@ -34,14 +34,13 @@ MA 02110-1301, USA.
#import "OOTextureScaling.h"
static NSString * const kOOLogPlanetTextureGen = @"texture.planet.generate";
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";
#ifdef M_PI
#define PI M_PI // C99, apparently
#else
#define PI 3.1415926536
#endif
static BOOL GetShaderSource(NSString *shaderType, NSDictionary *shaderDict, NSString **outResult);
@implementation TextureStore
@ -333,145 +332,138 @@ GLuint max_texture_dimension = 512; // conservative start
return 0; // failed!
}
GLhandleARB fragment_shader_object = nil;
GLhandleARB vertex_shader_object = nil;
GLhandleARB fragment_shader_object = NULL;
GLhandleARB vertex_shader_object = NULL;
GLhandleARB shader_program = NULL;
NSString *fragmentSource = nil;
NSString *vertexSource = nil;
BOOL OK = YES;
if (!GetShaderSource(@"fragment", shaderDict, &fragmentSource)) return NULL;
if (fragmentSource == nil) [shaderDict objectForKey:@"glsl"];
if (!GetShaderSource(@"vertex", shaderDict, &vertexSource)) return NULL;
if (fragmentSource == nil && vertexSource == nil)
{
OOLog(kOOLogShaderInitFailed, @"Shader dictionary specifies neither vertex shader nor fragment shader:\n", shaderDict);
return NULL;
}
// check if we need to make a fragment shader
if ([shaderDict objectForKey:@"glsl"])
if (fragmentSource != nil)
{
GLhandleARB shader_object = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); // a fragment shader
if (!shader_object)
{
NSLog(@"GLSL ERROR: could not create a fragment shader with glCreateShaderObjectARB()");
return 0; // failed!
}
NSString* glslSourceString = (NSString*)[shaderDict objectForKey:@"glsl"];
const GLcharARB *fragment_string;
fragment_string = [glslSourceString 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);
NSLog(@"GLSL ERROR: shader code would not compile:\n%s\n\n%@\n\n", log, [shaderDict objectForKey:@"glsl"]);
return 0; // failed!
NSLog(kOOLogShaderInitFailed, @"GLSL ERROR: could not create a fragment shader with glCreateShaderObjectARB()");
OK = NO;
}
fragment_shader_object = shader_object;
}
else if ([shaderDict objectForKey:@"glsl-fragment"])
{
GLhandleARB shader_object = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); // a fragment shader
if (!shader_object)
if (OK)
{
NSLog(@"GLSL ERROR: could not create a fragment shader with glCreateShaderObjectARB()");
return 0; // failed!
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);
NSLog(kOOLogShaderInitFailed, @"GLSL ERROR: shader code would not compile:\n%s\n\n%@\n\n", log, fragmentSource);
OK = NO;
}
fragment_shader_object = shader_object;
}
NSString* glslSourceString = (NSString*)[shaderDict objectForKey:@"glsl-fragment"];
const GLcharARB *fragment_string;
fragment_string = [glslSourceString 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);
NSLog(@"GLSL ERROR: shader code would not compile:\n%s\n\n%@\n\n", log, [shaderDict objectForKey:@"glsl-fragment"]);
return 0; // failed!
}
fragment_shader_object = shader_object;
}
// check if we need to make a vertex shader
if ([shaderDict objectForKey:@"glsl-vertex"])
if (vertexSource)
{
GLhandleARB shader_object = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); // a vertex shader
if (!shader_object)
{
NSLog(@"GLSL ERROR: could not create a vertex shader with glCreateShaderObjectARB()");
return 0; // failed!
NSLog(kOOLogShaderInitFailed, @"GLSL ERROR: could not create a fragment shader with glCreateShaderObjectARB()");
OK = NO;
}
NSString* glslSourceString = (NSString*)[shaderDict objectForKey:@"glsl-vertex"];
const GLcharARB *vertex_string;
vertex_string = [glslSourceString cString];
glShaderSourceARB( shader_object, 1, &vertex_string, NULL);
if (OK)
{
const GLcharARB *vertex_string;
vertex_string = [vertexSource cString];
glShaderSourceARB(shader_object, 1, &vertex_string, NULL);
// compile the shader!
glCompileShaderARB( shader_object);
// 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_object, GL_OBJECT_COMPILE_STATUS_ARB, &result);
glGetObjectParameterivARB(shader_program, GL_OBJECT_LINK_STATUS_ARB, &result);
if (result != GL_TRUE)
{
char log[1024];
GLsizei log_length;
glGetInfoLogARB( shader_object, 1024, &log_length, log);
NSLog(@"GLSL ERROR: shader code would not compile:\n%s\n\n%@\n\n", log, [shaderDict objectForKey:@"glsl-vertex"]);
return 0; // failed!
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;
}
vertex_shader_object = shader_object;
}
if (vertex_shader_object != NULL) glDeleteObjectARB(vertex_shader_object);
if (fragment_shader_object != NULL) glDeleteObjectARB(fragment_shader_object);
if (!OK && shader_program != NULL) 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];
}
if ((!fragment_shader_object)&&(!vertex_shader_object))
{
NSLog(@"GLSL ERROR: could not create any shaders from %@", shaderDict);
return 0; // failed!
}
// create a shader program
GLhandleARB shader_program = glCreateProgramObjectARB();
if (!shader_program)
{
NSLog(@"GLSL ERROR: could not create a shader program with glCreateProgramObjectARB()");
return 0; // failed!
}
// attach the shader objects
if (vertex_shader_object)
{
glAttachObjectARB( shader_program, vertex_shader_object);
glDeleteObjectARB( vertex_shader_object); /* Release */
}
if (fragment_shader_object)
{
glAttachObjectARB( shader_program, fragment_shader_object);
glDeleteObjectARB( fragment_shader_object); /* Release */
}
// 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);
NSLog(@"GLSL ERROR: shader program would not link:\n%s\n\n%@\n\n", log, shaderDict);
return 0; // failed!
}
// store the resulting program for reuse
if (!shaderUniversalDictionary)
shaderUniversalDictionary = [[NSMutableDictionary dictionary] retain];
[shaderUniversalDictionary setObject: [NSNumber numberWithUnsignedInt: (unsigned int) shader_program] forKey: shaderDict];
return shader_program;
return OK ? shader_program : NULL;
}
#endif
@ -672,7 +664,7 @@ void fillRanNoiseBuffer()
float my_lerp( float v0, float v1, float q)
{
float q1 = 0.5 * (1.0 + cosf((q + 1.0) * PI));
float q1 = 0.5 * (1.0 + cosf((q + 1.0) * M_PI));
return v0 * (1.0 - q1) + v1 * q1;
}
@ -917,3 +909,38 @@ 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;
shaderName = [shaderDict objectForKey:[shaderType stringByAppendingString:@"_shader"]];
if (shaderName != nil)
{
result = [ResourceManager stringFromFilesNamed:shaderName inFolder:@"Shaders"];
if (result == nil && ![[[shaderName pathExtension] lowercaseString] isEqual:shaderType])
{
// Futureproofing -- in future, we may wish to support automatic selection between supported shader languages.
result = [ResourceManager stringFromFilesNamed:[shaderName stringByAppendingPathExtension:@"fragment"]
inFolder:@"Shaders"];
}
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;
}