62 NSMutableDictionary *uniforms;
66static void SetUniform(NSMutableDictionary *uniforms, NSString *key, NSString *type,
id value);
88@implementation OOMaterial (OOConvenienceCreators)
90#if !USE_NEW_SHADER_SYNTHESIZER
92+ (NSDictionary *)synthesizeMaterialDictionaryWithName:(NSString *)name
93 configuration:(NSDictionary *)configuration
94 macros:(NSDictionary *)macros
96 if (configuration ==
nil) configuration = [NSDictionary dictionary];
99 .inConfig = configuration,
100 .outConfig = [NSMutableDictionary dictionary],
103 .macros = [NSMutableDictionary dictionaryWithDictionary:macros],
104 .textures = [NSMutableArray array],
105 .uniforms = [NSMutableDictionary dictionary]
128 [context.uniforms setObject:@"hullHeatLevel" forKey:@"uHullHeatLevel"];
129 [context.uniforms setObject:@"timeElapsedSinceSpawn" forKey:@"uTime"];
130 [context.uniforms setObject:@"fogUniform" forKey:@"uFogColor"];
134 [context.outConfig setObject:@"true" forKey:@"_oo_is_synthesized_config"];
135 [context.outConfig setObject:@"oolite-tangent-space-vertex.vertex" forKey:@"vertex_shader"];
136 [context.outConfig setObject:@"oolite-default-shader.fragment" forKey:@"fragment_shader"];
138 if ([context.
textures count] != 0) [context.outConfig setObject:context.textures forKey:@"textures"];
139 if ([context.
uniforms count] != 0) [context.outConfig setObject:context.uniforms forKey:@"uniforms"];
140 if ([context.
macros count] != 0) [context.outConfig setObject:context.macros forKey:@"_oo_synthesized_material_macros"];
146+ (
OOMaterial *)defaultShaderMaterialWithName:(NSString *)name
147 cacheKey:(NSString *)cacheKey
148 configuration:(NSDictionary *)configuration
149 macros:(NSDictionary *)macros
150 bindingTarget:(
id<OOWeakReferenceSupport>)target
153 NSDictionary *synthesizedConfig =
nil;
157 if ([configuration objectForKey:
@"_oo_is_synthesized_config"] !=
nil)
159 OOLog(
@"material.synthesize.loop",
@"Synthesis loop for material %@.", name);
168 cacheKey = [NSString stringWithFormat:@"%@/%@/%@", cacheKey, name, configuration];
172 if (synthesizedConfig ==
nil)
174 synthesizedConfig = [
self synthesizeMaterialDictionaryWithName:name
175 configuration:configuration
177 if (synthesizedConfig !=
nil && cacheKey !=
nil)
181 inCache:@"synthesized shader materials"];
185 if (synthesizedConfig !=
nil)
187 result = [
self materialWithName:name
189 configuration:synthesizedConfig
190 macros:[synthesizedConfig objectForKey:@"_oo_synthesized_material_macros"]
192 forSmoothedMesh:YES];
201static BOOL sDumpShaderSource = NO;
205 sDumpShaderSource = [[NSUserDefaults standardUserDefaults] boolForKey:@"dump-synthesized-shaders"];
210+ (
OOMaterial *) defaultShaderMaterialWithName:(NSString *)name
211 cacheKey:(NSString *)cacheKey
212 configuration:(NSDictionary *)configuration
213 macros:(NSDictionary *)macros
214 bindingTarget:(
id<OOWeakReferenceSupport>)target
216 NSString *vertexShader =
nil;
217 NSString *fragmentShader =
nil;
218 NSArray *textureSpecs =
nil;
219 NSDictionary *uniformSpecs =
nil;
221 if (!
OOSynthesizeMaterialShader(configuration, name, cacheKey , &vertexShader, &fragmentShader, &textureSpecs, &uniformSpecs))
226 NSDictionary *synthesizedConfig = [NSDictionary dictionaryWithObjectsAndKeys:
227 [NSNumber numberWithBool:YES], kOOIsSynthesizedMaterialConfigurationKey,
228 textureSpecs, kOOTexturesKey,
229 uniformSpecs, kOOUniformsKey,
230 vertexShader, kOOVertexShaderSourceKey,
231 fragmentShader, kOOFragmentShaderSourceKey,
235 if (sDumpShaderSource)
237 NSString *dumpPath = [NSString stringWithFormat:@"Synthesized Materials/%@/%@", cacheKey, name];
243 NSMutableDictionary *humanFriendlyConfig = [[synthesizedConfig mutableCopy] autorelease];
244 [humanFriendlyConfig removeObjectForKey:kOOVertexShaderSourceKey];
245 [humanFriendlyConfig removeObjectForKey:kOOFragmentShaderSourceKey];
246 [humanFriendlyConfig removeObjectForKey:kOOIsSynthesizedMaterialConfigurationKey];
247 [humanFriendlyConfig setObject:[NSString stringWithFormat:@"%@.vertex", name] forKey:kOOVertexShaderNameKey];
248 [humanFriendlyConfig setObject:[NSString stringWithFormat:@"%@.fragment", name] forKey:kOOFragmentShaderNameKey];
256 return [
self materialWithName:name
258 configuration:synthesizedConfig
261 forSmoothedMesh:YES];
267+ (
OOMaterial *) materialWithName:(NSString *)name
268 cacheKey:(NSString *)cacheKey
269 configuration:(NSDictionary *)configuration
270 macros:(NSDictionary *)macros
271 bindingTarget:(
id<OOWeakReferenceSupport>)object
272 forSmoothedMesh:(BOOL)smooth
280 if ([OOShaderMaterial configurationDictionarySpecifiesShaderMaterial:configuration])
282 result = [OOShaderMaterial shaderMaterialWithName:name
283 configuration:configuration
285 bindingTarget:object];
293 [configuration oo_combinedSpecularMapSpecifier] !=
nil ||
294 [configuration oo_normalMapSpecifier] !=
nil ||
295 [configuration oo_parallaxMapSpecifier] !=
nil ||
296 [configuration oo_normalAndParallaxMapSpecifier] !=
nil ||
297 [configuration oo_emissionMapSpecifier] !=
nil ||
298 [configuration oo_illuminationMapSpecifier] !=
nil ||
299 [configuration oo_emissionAndIlluminationMapSpecifier] !=
nil
302 result = [
self defaultShaderMaterialWithName:name
304 configuration:configuration
306 bindingTarget:(id<OOWeakReferenceSupport>)object];
314 if ([configuration oo_emissionMapSpecifier] !=
nil ||
315 [configuration oo_illuminationMapSpecifier] ||
316 [configuration oo_emissionAndIlluminationMapSpecifier] !=
nil)
318 result = [[OOMultiTextureMaterial alloc] initWithName:name configuration:configuration];
319 [result autorelease];
326 if ([configuration oo_diffuseMapSpecifierWithDefaultName:name] ==
nil)
328 result = [[
OOBasicMaterial alloc] initWithName:name configuration:configuration];
336 result = [[
OOBasicMaterial alloc] initWithName:name configuration:configuration];
338 [result autorelease];
344+ (
OOMaterial *) materialWithName:(NSString *)name
345 cacheKey:(NSString *)cacheKey
346 materialDictionary:(NSDictionary *)materialDict
347 shadersDictionary:(NSDictionary *)shadersDict
348 macros:(NSDictionary *)macros
349 bindingTarget:(
id<OOWeakReferenceSupport>)object
350 forSmoothedMesh:(BOOL)smooth
352 NSDictionary *configuration =
nil;
358 configuration = [shadersDict oo_dictionaryForKey:name];
362 if (configuration ==
nil)
364 configuration = [materialDict oo_dictionaryForKey:name];
367 if (configuration ==
nil)
372 if (texture ==
nil)
return nil;
374 configuration = [NSDictionary dictionary];
377 return [
self materialWithName:name
379 configuration:configuration
382 forSmoothedMesh:smooth];
388#if !USE_NEW_SHADER_SYNTHESIZER
390static void SetUniform(NSMutableDictionary *uniforms, NSString *key, NSString *type,
id value)
392 [uniforms setObject:[NSDictionary dictionaryWithObjectsAndKeys:type, @"type", value, @"value", nil] forKey:key];
408 [context->textures addObject:specifier];
409 if (nonShaderKey !=
nil)
411 [context->outConfig setObject:specifier forKey:kOOMaterialDiffuseMapName];
413 if (macroName !=
nil)
415 [context->macros setObject:@"1" forKey:macroName];
422 OOColor *color = [context->inConfig performSelector:selector];
427 if (macroName !=
nil) [context->macros setObject:@"1" forKey:macroName];
434 OOColor *color = [context->inConfig performSelector:selector];
438 NSString *macroText = [NSString stringWithFormat:@"vec4(%g, %g, %g, %g)",
443 [context->macros setObject:macroText forKey:macroName];
451 NSDictionary *diffuseMapSpec = [context->inConfig oo_diffuseMapSpecifierWithDefaultName:name];
456 if ([diffuseMapSpec oo_boolForKey:
@"cube_map"])
458 [context->macros setObject:@"1" forKey:@"OOSTD_DIFFUSE_MAP_IS_CUBE_MAP"];
464 [context->outConfig setObject:@"" forKey:kOOMaterialDiffuseMapName];
475 NSDictionary *emissionMapSpec = [context->inConfig oo_emissionMapSpecifier];
476 NSDictionary *illuminationMapSpec = [context->inConfig oo_illuminationMapSpecifier];
477 NSDictionary *emissionAndIlluminationSpec = [context->inConfig oo_emissionAndIlluminationMapSpecifier];
478 BOOL isCombinedSpec = NO;
479 BOOL haveIlluminationMap = NO;
481 if (emissionMapSpec ==
nil && emissionAndIlluminationSpec !=
nil)
483 emissionMapSpec = emissionAndIlluminationSpec;
484 if (illuminationMapSpec ==
nil) isCombinedSpec = YES;
496 AddTexture(context,
@"uEmissionMap",
nil, isCombinedSpec ?
@"OOSTD_EMISSION_AND_ILLUMINATION_MAP" :
@"OOSTD_EMISSION_MAP", emissionMapSpec);
503 haveIlluminationMap = isCombinedSpec;
513 AddTexture(context,
@"uIlluminationMap",
nil,
@"OOSTD_ILLUMINATION_MAP", illuminationMapSpec);
514 haveIlluminationMap = YES;
517 if (haveIlluminationMap)
528 BOOL hasParallax = YES;
529 NSDictionary *normalMapSpec = [context->inConfig oo_normalAndParallaxMapSpecifier];
530 if (normalMapSpec ==
nil)
533 normalMapSpec = [context->inConfig oo_normalMapSpecifier];
536 if (normalMapSpec !=
nil)
538 AddTexture(context,
@"uNormalMap",
nil,
@"OOSTD_NORMAL_MAP", normalMapSpec);
542 [context->macros setObject:@"1" forKey:@"OOSTD_NORMAL_AND_PARALLAX_MAP"];
553 GLint shininess = [context->inConfig oo_specularExponent];
554 if (shininess <= 0)
return;
556 GLfloat gloss = [context->inConfig oo_gloss];
557 if (gloss < 0.0f || gloss > 1.0f)
return;
559 BOOL gammaCorrect = [context->inConfig oo_gammaCorrect];
561 NSDictionary *specularMapSpec =
nil;
566 specularMapSpec = [context->inConfig oo_combinedSpecularMapSpecifier];
569 if (specularMapSpec !=
nil) specularColor = [context->inConfig oo_specularModulateColor];
570 else specularColor = [context->inConfig oo_specularColor];
571 if ([specularColor isBlack])
return;
575 [context->outConfig setObject:[NSNumber numberWithUnsignedInt:shininess] forKey:kOOMaterialSpecularExponentLegacyName];
577 if (specularMapSpec !=
nil)
582 if (specularColor !=
nil)
588 [context->outConfig setObject:[specularColor
normalizedArray] forKey:kOOMaterialSpecularColorName];
590 [context->macros setObject:@"1" forKey:@"OOSTD_SPECULAR"];
id textureWithName:inFolder:(NSString *name,[inFolder] NSString *directory)