595- (NSUInteger) assignIDForTexture:(NSDictionary *)spec
597 NSParameterAssert(spec !=
nil);
602 spec = [
spec dictionaryByRemovingObjectForKey:kOOTextureSpecifierSwizzleKey];
605 NSString *texName =
nil;
607 float anisotropy, lodBias;
611 [
NSException raise:NSGenericException format:@"Invalid texture specifier"];
617 OOLogERR(
@"material.synthesis.error.cubeMap",
@"The material \"%@\
" of \"%@\" specifies a cube map texture, but doesn't have custom shaders. Cube map textures are not supported with the default shaders.", [
self materialKey], [
self entityName]);
618 [
NSException raise:NSGenericException format:@"Invalid material"];
623 NSObject *existing = [_texturesByName objectForKey:key];
626 texID = [_texturesByName count];
627 NSNumber *texIDObj = [
NSNumber numberWithUnsignedInteger:texID];
628 NSString *texUniform = [
NSString stringWithFormat:@"uTexture%lu", texID];
631 BOOL useInternalFormat = NO;
633 BOOL useInternalFormat = YES;
636 [_textures addObject:OOMakeTextureSpecifier(texName, texOptions, anisotropy, lodBias, useInternalFormat)];
637 [_texturesByName setObject:spec forKey:key];
638 [_textureIDs setObject:texIDObj forKey:key];
639 [_uniforms setObject:[
NSDictionary dictionaryWithObjectsAndKeys:@"texture", @"type", texIDObj, @"value", nil]
646 texID = [_textureIDs oo_unsignedIntegerForKey:texName];
1033 float specularExponent = [_configuration oo_specularExponent];
1034 if (specularExponent <= 0)
return;
1036 NSDictionary *specularColorMap = [_configuration oo_specularColorMapSpecifier];
1037 NSDictionary *specularExponentMap = [_configuration oo_specularExponentMapSpecifier];
1038 float scaleFactor = 1.0f;
1040 if (specularColorMap)
1042 scaleFactor = [
specularColorMap oo_doubleForKey:kOOTextureSpecifierScaleFactorKey defaultValue:1.0f];
1046 if (specularColorMap ==
nil)
1048 specularColor = [_configuration oo_specularColor];
1052 specularColor = [_configuration oo_specularModulateColor];
1055 if ([specularColor isBlack])
return;
1057 BOOL modulateWithDiffuse = [
specularColorMap oo_boolForKey:kOOTextureSpecifierSelfColorKey];
1063 if (modulateWithDiffuse)
1068 [_fragmentBody appendString:@"\t// Specular (Blinn-Phong) lighting\n"];
1070 BOOL haveSpecularColor = NO;
1071 if (specularColorMap !=
nil)
1076 [_fragmentBody appendString:@"\t// INVALID EXTRACTION KEY\n\t\n"];
1080 [_fragmentBody appendFormat:@"\tvec3 specularColor = %@;\n", readInstr];
1081 haveSpecularColor = YES;
1084 if (!haveSpecularColor || ![specularColor isWhite])
1089 NSString *comment = (scaleFactor == 1.0f) ?
@"Constant colour" :
@"Constant colour and scale factor";
1092 scaleFactor *= rgba[3];
1093 rgba[0] *= scaleFactor;
1094 rgba[1] *= scaleFactor;
1095 rgba[2] *= scaleFactor;
1100 NSString *format =
nil;
1101 if (haveSpecularColor)
1103 format =
@"\tspecularColor *= vec3(%@, %@, %@); // %@\n";
1107 format =
@"\tvec3 specularColor = vec3(%@, %@, %@); // %@\n";
1108 haveSpecularColor = YES;
1110 [_fragmentBody appendFormat:format, FormatFloat(rgba[0]), FormatFloat(rgba[1]), FormatFloat(rgba[2]), comment];
1114 if (haveSpecularColor && scaleFactor != 1.0f)
1116 [_fragmentBody appendFormat:@"\tspecularColor *= %@; // Scale factor\n", FormatFloat(scaleFactor)];
1120 if (modulateWithDiffuse)
1122 [_fragmentBody appendString:@"\tspecularColor *= diffuseColor; // Self-colouring\n"];
1126 BOOL haveSpecularExponent = NO;
1127 if (specularExponentMap !=
nil)
1132 [_fragmentBody appendString:@"\t// INVALID EXTRACTION KEY\n\t\n"];
1136 [_fragmentBody appendFormat:@"\tfloat specularExponent = %@ * %.1f;\n", readInstr, specularExponent];
1137 haveSpecularExponent = YES;
1139 if (!haveSpecularExponent)
1141 [_fragmentBody appendFormat:@"\tconst float specularExponent = %.1f;\n", specularExponent];
1146 [_fragmentBody appendFormat:@"\tvec3 reflection = reflect(lightVector, normal);\n"];
1153 [_fragmentBody appendFormat:@"\tvec3 reflection = vec3(lightVector.x, lightVector.y, -lightVector.z); // Equivalent to reflect(lightVector, normal) since normal is known to be (0, 0, 1) in tangent space.\n"];
1156 [_fragmentBody appendFormat:
1157 @"\tfloat specIntensity = dot(reflection, eyeVector);\n"
1158 "\tspecIntensity = pow(max(0.0, specIntensity), specularExponent);\n"
1159 "\ttotalColor += specIntensity * specularColor * gl_LightSource[1].specular.rgb;\n\t\n"];
1165 NSArray *lightMaps = [_configuration oo_arrayForKey:kOOMaterialLightMapsName];
1167 if (
count == 0)
return;
1172 for (idx = 0; idx <
count; idx++)
1174 NSDictionary *lightMapSpec = [
lightMaps oo_dictionaryAtIndex:idx];
1183 [_fragmentBody appendString:@"\tvec3 lightMapColor;\n"];
1185 for (idx = 0; idx <
count; idx++)
1187 NSDictionary *lightMapSpec = [
lightMaps oo_dictionaryAtIndex:idx];
1189 NSArray *color = [
lightMapSpec oo_arrayForKey:kOOTextureSpecifierModulateColorKey];
1190 float rgba[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
1191 BOOL isIllumination = [
lightMapSpec oo_boolForKey:kOOTextureSpecifierIlluminationModeKey];
1195 [_fragmentBody appendString:@"\t// Light map with neither colour nor texture has no effect.\n\t\n"];
1203 for (idx = 0; idx <
count; idx++)
1205 rgba[
idx] = [
color oo_doubleAtIndex:idx];
1207 rgba[0] *= rgba[3]; rgba[1] *= rgba[3]; rgba[2] *= rgba[3];
1210 if (
EXPECT_NOT((rgba[0] == 0.0f && rgba[1] == 0.0f && rgba[2] == 0.0f) ||
1213 [_fragmentBody appendString:@"\t// Light map tinted black has no effect.\n\t\n"];
1217 if (textureSpec !=
nil)
1222 [_fragmentBody appendString:@"\t// INVALID EXTRACTION KEY\n\n"];
1226 [_fragmentBody appendFormat:@"\tlightMapColor = %@;\n", readInstr];
1228 if (rgba[0] != 1.0f || rgba[1] != 1.0f || rgba[2] != 1.0f)
1230 [_fragmentBody appendFormat:@"\tlightMapColor *= vec3(%@, %@, %@);\n", FormatFloat(rgba[0]), FormatFloat(rgba[1]), FormatFloat(rgba[2])];
1235 [_fragmentBody appendFormat:@"\tlightMapColor = vec3(%@, %@, %@);\n", FormatFloat(rgba[0]), FormatFloat(rgba[1]), FormatFloat(rgba[2])];
1238 NSDictionary *binding = [
textureSpec oo_dictionaryForKey:kOOTextureSpecifierBindingKey];
1241 NSString *bindingName = [
binding oo_stringForKey:@"binding"];
1243 NSString *bindingType = [
typeDict oo_stringForKey:bindingName];
1244 NSString *glslType =
nil;
1245 NSString *swizzle =
@"";
1247 if ([bindingType isEqualToString:
@"float"])
1249 glslType =
@"float";
1251 else if ([bindingType isEqualToString:
@"vector"])
1255 else if ([bindingType isEqualToString:
@"color"])
1261 if (glslType !=
nil)
1264 [_fragmentBody appendFormat:@"\tlightMapColor *= %@%@;\n", uniformName, swizzle];
1268 if (bindingType ==
nil)
1270 OOLogERR(
@"material.binding.error.unknown",
@"Cannot bind light map to unknown attribute \"%@\
".", bindingName);
1274 OOLogERR(
@"material.binding.error.badType",
@"Cannot bind light map to attribute \"%@\
" of type %@.", bindingName, bindingType);
1276 [_fragmentBody appendString:@"\tlightMapColor = vec3(0.0); // Bad binding, see log.\n"];
1280 if (!isIllumination)
1282 [_fragmentBody appendString:@"\ttotalColor += lightMapColor;\n\t\n"];
1286 [_fragmentBody appendString:@"\tdiffuseLight += lightMapColor;\n\t\n"];
1332 NSMutableDictionary *result = [NSMutableDictionary dictionary];
1339 if (col !=
nil) [result setObject:[col
normalizedArray] forKey:kOOMaterialDiffuseColorName];
1343 if (col !=
nil) [result setObject:[col
normalizedArray] forKey:kOOMaterialAmbientColorName];
1347 if (col !=
nil) [result setObject:[col
normalizedArray] forKey:kOOMaterialSpecularColorName];
1350 if (col !=
nil) [result setObject:[col
normalizedArray] forKey:kOOMaterialSpecularModulateColorName];
1354 if (col !=
nil) [result setObject:[col
normalizedArray] forKey:kOOMaterialEmissionColorName];
1357 texSpec = [spec objectForKey:kOOMaterialDiffuseMapName];
1358 if ([texSpec isKindOfClass:[NSString
class]])
1360 if ([texSpec length] > 0)
1362 texSpec = [NSDictionary dictionaryWithObject:texSpec forKey:kOOTextureSpecifierNameKey];
1365 else if ([texSpec isKindOfClass:[NSDictionary
class]])
1370 NSString *name = [texSpec objectForKey:kOOTextureSpecifierNameKey];
1371 if (name ==
nil) texSpec = [texSpec dictionaryByAddingObject:materialKey forKey:kOOTextureSpecifierNameKey];
1372 else if ([name length] == 0)
1374 texSpec = [texSpec dictionaryByRemovingObjectForKey:kOOTextureSpecifierNameKey];
1380 texSpec = [NSDictionary dictionaryWithObject:materialKey forKey:kOOTextureSpecifierNameKey];
1382 [result setObject:texSpec forKey:kOOMaterialDiffuseMapName];
1386 BOOL haveNewSpecular = NO;
1387 texSpec = [spec objectForKey:kOOMaterialSpecularColorMapName];
1388 if ([texSpec isKindOfClass:[NSString
class]])
1390 texSpec = [NSDictionary dictionaryWithObject:texSpec forKey:kOOTextureSpecifierNameKey];
1392 else if (![texSpec isKindOfClass:[NSDictionary
class]])
1398 haveNewSpecular = YES;
1399 [result setObject:texSpec forKey:kOOMaterialSpecularColorMapName];
1402 texSpec = [spec objectForKey:kOOMaterialSpecularExponentMapName];
1403 if ([texSpec isKindOfClass:[NSString
class]])
1405 texSpec = [NSDictionary dictionaryWithObject:texSpec forKey:kOOTextureSpecifierNameKey];
1407 else if (![texSpec isKindOfClass:[NSDictionary
class]])
1413 haveNewSpecular = YES;
1414 [result setObject:texSpec forKey:kOOMaterialSpecularExponentMapName];
1417 if (!haveNewSpecular)
1420 texSpec = [spec objectForKey:kOOMaterialCombinedSpecularMapName];
1421 if ([texSpec isKindOfClass:[NSString
class]])
1423 texSpec = [NSDictionary dictionaryWithObject:texSpec forKey:kOOTextureSpecifierNameKey];
1425 else if (![texSpec isKindOfClass:[NSDictionary
class]])
1431 [result setObject:texSpec forKey:kOOMaterialSpecularColorMapName];
1432 texSpec = [texSpec dictionaryByAddingObject:@"a" forKey:kOOTextureSpecifierSwizzleKey];
1433 [result setObject:texSpec forKey:kOOMaterialSpecularExponentMapName];
1440 BOOL haveParallax = NO;
1441 BOOL haveNewNormal = NO;
1442 texSpec = [spec objectForKey:kOOMaterialNormalMapName];
1443 if ([texSpec isKindOfClass:[NSString
class]])
1445 texSpec = [NSDictionary dictionaryWithObject:texSpec forKey:kOOTextureSpecifierNameKey];
1447 else if (![texSpec isKindOfClass:[NSDictionary
class]])
1453 haveNewNormal = YES;
1454 [result setObject:texSpec forKey:kOOMaterialNormalMapName];
1457 texSpec = [spec objectForKey:kOOMaterialParallaxMapName];
1458 if ([texSpec isKindOfClass:[NSString
class]])
1460 texSpec = [NSDictionary dictionaryWithObject:texSpec forKey:kOOTextureSpecifierNameKey];
1462 else if (![texSpec isKindOfClass:[NSDictionary
class]])
1468 haveNewNormal = YES;
1470 [result setObject:texSpec forKey:kOOMaterialParallaxMapName];
1476 texSpec = [spec objectForKey:kOOMaterialNormalAndParallaxMapName];
1477 if ([texSpec isKindOfClass:[NSString
class]])
1479 texSpec = [NSDictionary dictionaryWithObject:texSpec forKey:kOOTextureSpecifierNameKey];
1481 else if (![texSpec isKindOfClass:[NSDictionary
class]])
1488 [result setObject:texSpec forKey:kOOMaterialNormalMapName];
1489 texSpec = [texSpec dictionaryByAddingObject:@"a" forKey:kOOTextureSpecifierSwizzleKey];
1490 [result setObject:texSpec forKey:kOOMaterialParallaxMapName];
1497 float parallaxScale = [spec oo_floatForKey:kOOMaterialParallaxScaleName defaultValue:kOOMaterialDefaultParallaxScale];
1498 [result oo_setFloat:parallaxScale forKey:kOOMaterialParallaxScaleName];
1500 float parallaxBias = [spec oo_floatForKey:kOOMaterialParallaxBiasName];
1501 [result oo_setFloat:parallaxBias forKey:kOOMaterialParallaxBiasName];
1507 NSMutableArray *lightMaps = [NSMutableArray array];
1508 id lightMapSpecs = [spec objectForKey:kOOMaterialLightMapsName];
1509 if (lightMapSpecs !=
nil && ![lightMapSpecs isKindOfClass:[NSArray
class]])
1511 lightMapSpecs = [NSArray arrayWithObject:lightMapSpecs];
1515 foreach (lmSpec, lightMapSpecs)
1517 if ([lmSpec isKindOfClass:[NSString
class]])
1519 lmSpec = [NSMutableDictionary dictionaryWithObject:lmSpec forKey:kOOTextureSpecifierNameKey];
1521 else if ([lmSpec isKindOfClass:[NSDictionary
class]])
1523 lmSpec = [[lmSpec mutableCopy] autorelease];
1530 id modulateColor = [lmSpec objectForKey:kOOTextureSpecifierModulateColorKey];
1531 if (modulateColor !=
nil && ![modulateColor isKindOfClass:[NSArray
class]])
1535 [lmSpec setObject:[col
normalizedArray] forKey:kOOTextureSpecifierModulateColorKey];
1538 id binding = [lmSpec objectForKey:kOOTextureSpecifierBindingKey];
1541 if ([binding isKindOfClass:[NSString
class]])
1543 NSDictionary *expandedBinding = [NSDictionary dictionaryWithObjectsAndKeys:@"binding", @"type", binding, @"binding", nil];
1544 [lmSpec setObject:expandedBinding forKey:kOOTextureSpecifierBindingKey];
1546 else if (![binding isKindOfClass:[NSDictionary
class]] || [[binding oo_stringForKey:
@"binding"] length] == 0)
1548 [lmSpec removeObjectForKey:kOOTextureSpecifierBindingKey];
1552 [lightMaps addObject:[[lmSpec copy] autorelease]];
1555 if ([lightMaps
count] == 0)
1558 id emissionSpec = [spec objectForKey:kOOMaterialEmissionMapName];
1559 id illuminationSpec = [spec objectForKey:kOOMaterialIlluminationMapName];
1561 if (emissionSpec ==
nil && illuminationSpec ==
nil)
1563 emissionSpec = [spec objectForKey:kOOMaterialEmissionAndIlluminationMapName];
1564 if ([emissionSpec isKindOfClass:[NSString
class]])
1567 emissionSpec = [NSDictionary dictionaryWithObject:emissionSpec forKey:kOOTextureSpecifierNameKey];
1569 else if (![emissionSpec isKindOfClass:[NSDictionary
class]])
1574 if (emissionSpec !=
nil)
1576 illuminationSpec = [emissionSpec dictionaryByAddingObject:@"a" forKey:kOOTextureSpecifierSwizzleKey];
1580 if (emissionSpec !=
nil)
1582 if ([emissionSpec isKindOfClass:[NSString
class]])
1584 emissionSpec = [NSDictionary dictionaryWithObject:emissionSpec forKey:kOOTextureSpecifierNameKey];
1586 if ([emissionSpec isKindOfClass:[NSDictionary
class]])
1589 if (col !=
nil) emissionSpec = [emissionSpec dictionaryByAddingObject:[col
normalizedArray] forKey:kOOTextureSpecifierModulateColorKey];
1591 [lightMaps addObject:emissionSpec];
1595 if (illuminationSpec !=
nil)
1597 if ([illuminationSpec isKindOfClass:[NSString
class]])
1599 illuminationSpec = [NSDictionary dictionaryWithObject:illuminationSpec forKey:kOOTextureSpecifierNameKey];
1601 if ([illuminationSpec isKindOfClass:[NSDictionary
class]])
1604 if (col !=
nil) illuminationSpec = [illuminationSpec dictionaryByAddingObject:[col
normalizedArray] forKey:kOOTextureSpecifierModulateColorKey];
1606 illuminationSpec = [illuminationSpec dictionaryByAddingObject:[NSNumber numberWithBool:YES] forKey:kOOTextureSpecifierIlluminationModeKey];
1608 [lightMaps addObject:illuminationSpec];
1613 [result setObject:lightMaps forKey:kOOMaterialLightMapsName];
1616 OOLog(
@"material.canonicalForm",
@"Canonicalized material %@:\nORIGINAL:\n%@\n\n@CANONICAL:\n%@",
materialKey, spec, result);
BOOL OOInterpretTextureSpecifier(id specifier, NSString **outName, OOTextureFlags *outOptions, float *outAnisotropy, float *outLODBias, BOOL ignoreExtract)