Rudimentary planet shader (disabled with SHADY_PLANETS macro in OOPlanetEntity.m; texture mapping only, no lighting, but with per-pixel calculation of longitude component to completely eliminate distortion. Interacts badly with mip-mapping, though.)

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2860 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2009-12-07 22:42:23 +00:00
parent 8afb80c43c
commit 41f5d03697
12 changed files with 245 additions and 39 deletions

View File

@ -606,6 +606,8 @@
1AD1F4FF0CD9E83700EAE520 /* NSThreadOOExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AD1F4C80CD9E42A00EAE520 /* NSThreadOOExtensions.m */; };
1AD1F5000CD9E83800EAE520 /* NSThreadOOExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AD1F4C70CD9E42A00EAE520 /* NSThreadOOExtensions.h */; };
1ADA564810CD68D800E891B8 /* OOStellarBody.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ADA564710CD68D800E891B8 /* OOStellarBody.h */; };
1ADA576D10CDB1E700E891B8 /* oolite-default-planet.vertex in Copy Shaders */ = {isa = PBXBuildFile; fileRef = 1ADA576710CDB1C300E891B8 /* oolite-default-planet.vertex */; };
1ADA576E10CDB1E700E891B8 /* oolite-default-planet.fragment in Copy Shaders */ = {isa = PBXBuildFile; fileRef = 1ADA576910CDB1C600E891B8 /* oolite-default-planet.fragment */; };
1ADA8AB30F42DBA80001BEC9 /* OODeepCopy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ADA8AB10F42DBA80001BEC9 /* OODeepCopy.h */; };
1ADA8AB40F42DBA80001BEC9 /* OODeepCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ADA8AB20F42DBA80001BEC9 /* OODeepCopy.m */; };
1ADBA5500BD0F173008FC99C /* OOBasicMaterial.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ADBA54E0BD0F173008FC99C /* OOBasicMaterial.h */; };
@ -1066,6 +1068,8 @@
dstPath = Shaders;
dstSubfolderSpec = 7;
files = (
1ADA576D10CDB1E700E891B8 /* oolite-default-planet.vertex in Copy Shaders */,
1ADA576E10CDB1E700E891B8 /* oolite-default-planet.fragment in Copy Shaders */,
1A6515100CCC9E2E0054D01B /* oolite-standard-vertex.vertex in Copy Shaders */,
1A02FD460EE0490B008F9B09 /* oolite-tangent-space-vertex.vertex in Copy Shaders */,
1A6515110CCC9E2E0054D01B /* oolite-default-shader.fragment in Copy Shaders */,
@ -1697,6 +1701,8 @@
1AD6B3280E3BB55E001C42D9 /* debug-exports-64.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = "debug-exports-64.exp"; sourceTree = "<group>"; };
1AD88FAF103F29D300AA36F4 /* oolite-options.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "oolite-options.xcconfig"; path = "src/Cocoa/oolite-options.xcconfig"; sourceTree = "<group>"; };
1ADA564710CD68D800E891B8 /* OOStellarBody.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOStellarBody.h; sourceTree = "<group>"; };
1ADA576710CDB1C300E891B8 /* oolite-default-planet.vertex */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.frag; path = "oolite-default-planet.vertex"; sourceTree = "<group>"; };
1ADA576910CDB1C600E891B8 /* oolite-default-planet.fragment */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.vert; path = "oolite-default-planet.fragment"; sourceTree = "<group>"; };
1ADA8AB10F42DBA80001BEC9 /* OODeepCopy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OODeepCopy.h; sourceTree = "<group>"; };
1ADA8AB20F42DBA80001BEC9 /* OODeepCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OODeepCopy.m; sourceTree = "<group>"; };
1ADBA54E0BD0F173008FC99C /* OOBasicMaterial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOBasicMaterial.h; sourceTree = "<group>"; };
@ -2383,6 +2389,8 @@
1A65150D0CCC9E220054D01B /* oolite-standard-vertex.vertex */,
1A02FD340EE048E8008F9B09 /* oolite-tangent-space-vertex.vertex */,
1A65150E0CCC9E220054D01B /* oolite-default-shader.fragment */,
1ADA576710CDB1C300E891B8 /* oolite-default-planet.vertex */,
1ADA576910CDB1C600E891B8 /* oolite-default-planet.fragment */,
);
path = Shaders;
sourceTree = "<group>";

View File

@ -8,19 +8,41 @@
// Macros prepended to shader source code for ship entities.
"ship-prefix-macros" =
{
"OO_USER_DEFINED_BINDINGS" = 1;
"OO_TANGENT_ATTR" = 1;
OO_USER_DEFINED_BINDINGS = 1;
OO_TANGENT_ATTR = 1;
};
// Material definition used for DAT files with no TEXTURES section (which specifies material names and texture co-ordinates).
"no-textures-material" =
{
"diffuse_map" = "";
"diffuse" = (0, 0, 0.4);
"ambient" = (0, 0, 0.4);
"emission" = (0.9, 0.9, 0.9);
"specular" = (1.0, 0.8, 0.8);
"shininess" = 1;
diffuse_map = "";
diffuse = (0, 0, 0.4);
ambient = (0, 0, 0.4);
emission = (0.9, 0.9, 0.9);
specular = (1.0, 0.8, 0.8);
shininess = 1;
};
"planet-material" =
{
// Textures added dynamically.
vertex_shader = "oolite-default-planet.vertex";
fragment_shader = "oolite-default-planet.fragment";
uniforms =
{
uDiffuseMap = { type = texture; value = 0; };
uNormalMap = { type = texture; value = 1; };
};
};
"planet-synthetic-macros" =
{
OOSTD_DIFFUSE_AND_SPECULAR_MAP = 1;
OOSTD_CUBE_MAP = 0;
};
"planet-customized-macros" =
{
OOSTD_DIFFUSE_MAP = 1;
OOSTD_CUBE_MAP = 0;
};
}

View File

@ -0,0 +1,69 @@
#define OO_LIGHT_0_FIX 0
uniform sampler2D uDiffuseMap;
// No vNormal, because normal is always 0,0,1 in tangent space.
varying vec3 vEyeVector;
varying vec2 vTexCoords;
varying vec3 vLight0Vector;
varying vec3 vLight1Vector;
varying vec3 vNormal;
varying vec3 vCoords;
vec4 CalcDiffuseLight(in vec3 lightVector, in vec3 normal, in vec4 lightColor)
{
float intensity = lightVector.z;
intensity = max(intensity, 0.0);
return lightColor * intensity;
}
#ifndef OO_REDUCED_COMPLEXITY
/* Approximation of atan(y/z) with quadrant rectification, scaled to -0.5..0.5 instead of -pi..pi.
It is assumed that the values are in range. You are not expected to understand this.
*/
float TexLongitude(float z, float y)
{
const float k2Pi = 6.283185307179586;
const float kMagic = 0.2732395447351; // (4 - pi) / pi
float ratio = z / y;
float r1 = 1.0 / ((ratio + kMagic / ratio) * k2Pi); // Result when abs(y) >= abs(x).
float r2 = 0.25 * sign(ratio) - ratio / ((1.0 + kMagic * ratio * ratio) * k2Pi); // Result when abs(y) <= abs(x).
float result = (abs(ratio) > 1.0) ? r1 : r2;
// Adjust for sector.
// Equivalent to (z < 0.0) ? ((y > 0.0) ? 0.75 : -0.25) : 0.25.
// Well, technically not equivalent for z < 0, y = 0, but you'll very rarely see that exact case.
return result + step(z, 0.0) * sign(y) * 0.5 + 0.25;
}
#endif
void main()
{
/* Fun sphere facts: the normalized coordinates of a point on a sphere at the origin
is equal to the object-space normal of the surface at that point.
Furthermore, we can construct the binormal (a vector pointing westward along the
surface) as the cross product of the normal with the Y axis. (This produces
singularities at the pole, but there have to be singularities according to the
Hairy Ball Theorem.) The tangent (a vector north along the surface) is then the
inverse of the cross product of the normal and binormal.
*/
vec3 coords = normalize(vCoords);
#define normal coords
vec3 binormal = cross(normal, vec3(0, 1, 0));
vec3 tangent = -cross(normal, binormal);
#ifdef OO_REDUCED_COMPLEXITY
#define texCoords vTexCoords
#else
vec2 texCoords = vec2(TexLongitude(coords.x, coords.z), vTexCoords.t);
#endif
vec4 diffuseMapColor = texture2D(uDiffuseMap, texCoords);
gl_FragColor = diffuseMapColor;
}

View File

@ -0,0 +1,36 @@
attribute vec3 tangent;
// No vNormal, because normal is always 0,0,1 in tangent space.
varying vec3 vEyeVector;
varying vec2 vTexCoords;
varying vec3 vLight0Vector;
varying vec3 vLight1Vector;
varying vec3 vNormal;
varying vec3 vCoords;
void main(void)
{
vCoords = gl_Vertex.xyz;
// Build tangent basis
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * tangent);
vec3 b = cross(n, t);
vNormal = n;
mat3 TBN = mat3(t, b, n);
vec3 eyeVector = -vec3(gl_ModelViewMatrix * gl_Vertex);
vEyeVector = eyeVector * TBN;
vec3 light0Vector = gl_LightSource[0].position.xyz + eyeVector;
vLight0Vector = light0Vector * TBN;
vec3 light1Vector = /*gl_LightSource[1].position.xyz*/ vec3(30, 100, 50) + eyeVector;
vLight1Vector = light1Vector * TBN;
vTexCoords = gl_MultiTexCoord0.st;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

View File

@ -26,6 +26,8 @@ MA 02110-1301, USA.
#if NEW_PLANETS
#define SHADY_PLANETS 0
#import "OOPlanetDrawable.h"
#import "AI.h"
@ -34,11 +36,13 @@ MA 02110-1301, USA.
#import "OOCharacter.h"
#import "OOMaths.h"
#import "ResourceManager.h"
#import "OOStringParsing.h"
#import "OOCollectionExtractors.h"
#import "OOPlanetTextureGenerator.h"
#import "OOSingleTextureMaterial.h"
#import "OOShaderMaterial.h"
@interface OOPlanetEntity (Private)
@ -388,6 +392,7 @@ static OOColor *ColorWithHSBColor(Vector c)
- (void) setTextureFileName:(NSString *)textureName
{
#if !SHADY_PLANETS
if (textureName != nil)
{
[_planetDrawable setTextureName:textureName];
@ -399,8 +404,48 @@ static OOColor *ColorWithHSBColor(Vector c)
[_planetDrawable setMaterial:material];
[material release];
}
#else
OOTexture *diffuseMap = nil;
NSDictionary *macros = nil;
NSDictionary *materialDefaults = [ResourceManager materialDefaults];
#if !NO_SHADERS
OOShaderSetting shaderLevel = [UNIVERSE shaderEffectsLevel];
BOOL shadersOn = shaderLevel > SHADERS_OFF;
#else
const BOOL shadersOn = NO;
#endif
if (textureName != nil)
{
NSDictionary *spec = [NSDictionary dictionaryWithObjectsAndKeys:textureName, @"name", @"yes", @"repeat_s", @"linear", @"min_filter", nil];
diffuseMap = [OOTexture textureWithConfiguration:spec];
if (shadersOn) macros = [materialDefaults oo_dictionaryForKey:@"planet-customized-macros"];
}
else
{
diffuseMap = [OOPlanetTextureGenerator planetTextureWithInfo:_materialParameters];
if (shadersOn) macros = [materialDefaults oo_dictionaryForKey:@"planet-synthetic-macros"];
textureName = @"dynamic";
}
OOMaterial *material = nil;
#if !NO_SHADERS
if (shadersOn)
{
NSMutableDictionary *config = [[[materialDefaults oo_dictionaryForKey:@"planet-material"] mutableCopy] autorelease];
[config setObject:[NSArray arrayWithObjects:diffuseMap, nil] forKey:@"_oo_texture_objects"];
material = [OOShaderMaterial shaderMaterialWithName:textureName
configuration:config
macros:macros
bindingTarget:self];
}
#endif
if (material == nil)
{
material = [[OOSingleTextureMaterial alloc] initWithName:textureName texture:diffuseMap configuration:nil];
}
[_planetDrawable setMaterial:material];
#endif
}

View File

@ -9337,12 +9337,10 @@ static BOOL AuthorityPredicate(Entity *entity, void *parameter)
NSDictionary *DefaultShipShaderMacros(void)
{
static NSDictionary *macros = nil;
NSDictionary *materialDefaults = nil;
if (macros == nil)
{
materialDefaults = [ResourceManager dictionaryFromFilesNamed:@"material-defaults.plist" inFolder:@"Config" andMerge:YES];
macros = [[materialDefaults oo_dictionaryForKey:@"ship-prefix-macros" defaultValue:[NSDictionary dictionary]] retain];
macros = [[[ResourceManager materialDefaults] oo_dictionaryForKey:@"ship-prefix-macros" defaultValue:[NSDictionary dictionary]] retain];
}
return macros;

View File

@ -101,7 +101,7 @@ static FloatRGBA PlanetMix(float q, float maxQ, FloatRGB landColor, FloatRGB sea
- (uint32_t) textureOptions
{
return [super textureOptions] | kOOTextureRepeatS | kOOTextureNoShrink;
return kOOTextureMinFilterLinear | kOOTextureMagFilterLinear | kOOTextureRepeatS | kOOTextureNoShrink;
}

View File

@ -23,7 +23,7 @@ MA 02110-1301, USA.
This file may also be distributed under the MIT/X11 license:
Copyright (C) 2007 Jens Ayton
Copyright (C) 2007-2009 Jens Ayton
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -65,7 +65,11 @@ static NSString *MacrosToString(NSDictionary *macros);
@interface OOShaderMaterial (OOPrivate)
- (void)addTexturesFromArray:(NSArray *)textureNames unitCount:(GLuint)max;
// Convert a "textures" array to an "_oo_texture_objects" array.
- (NSArray *) loadTexturesFromArray:(NSArray *)textureSpecs unitCount:(GLuint)max;
// Load up an array of texture objects.
- (void) addTexturesFromArray:(NSArray *)textureObjects unitCount:(GLuint)max;
@end
@ -98,8 +102,6 @@ static NSString *MacrosToString(NSDictionary *macros);
bindingTarget:(id<OOWeakReferenceSupport>)target
{
BOOL OK = YES;
NSDictionary *uniformDefs = nil;
NSArray *textureDefs = nil;
NSString *macroString = nil;
NSString *vertexShader = nil;
NSString *fragmentShader = nil;
@ -160,14 +162,23 @@ static NSString *MacrosToString(NSDictionary *macros);
if (OK)
{
// Load uniforms
uniformDefs = [configuration oo_dictionaryForKey:@"uniforms"];
textureDefs = [configuration oo_arrayForKey:@"textures"];
// Load uniforms and textures, which are a flavour of uniform for our purpose.
NSDictionary *uniformDefs = [configuration oo_dictionaryForKey:@"uniforms"];
uniforms = [[NSMutableDictionary alloc] initWithCapacity:[uniformDefs count] + [textureDefs count]];
// ..
NSArray *textureArray = [configuration oo_arrayForKey:@"_oo_texture_objects"];
if (textureArray == nil)
{
NSArray *textureSpecs = [configuration oo_arrayForKey:@"textures"];
if (textureSpecs != nil)
{
textureArray = [self loadTexturesFromArray:textureSpecs unitCount:textureUnits];
}
}
uniforms = [[NSMutableDictionary alloc] initWithCapacity:[uniformDefs count] + [textureArray count]];
[self addUniformsFromDictionary:uniformDefs withBindingTarget:target];
// ...and textures, which are a flavour of uniform for our purpose.
[self addTexturesFromArray:textureDefs unitCount:textureUnits];
[self addTexturesFromArray:textureArray unitCount:textureUnits];
}
if (!OK)
@ -601,30 +612,43 @@ static NSString *MacrosToString(NSDictionary *macros);
@implementation OOShaderMaterial (OOPrivate)
- (void)addTexturesFromArray:(NSArray *)textureNames unitCount:(GLuint)max
- (NSArray *) loadTexturesFromArray:(NSArray *)textureSpecs unitCount:(GLuint)max
{
id textureDef = nil;
unsigned i = 0;
unsigned i, count = MIN([textureSpecs count], max);
NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];
// Allocate space for texture object name array
texCount = MAX(MIN(max, [textureNames count]), 0U);
if (texCount == 0) return;
for (i = 0; i < count; i++)
{
id textureSpec = [textureSpecs objectAtIndex:i];
OOTexture *texture = [OOTexture textureWithConfiguration:textureSpec];
if (texture == nil) texture = [OOTexture nullTexture];
[result addObject:texture];
}
return result;
}
- (void) addTexturesFromArray:(NSArray *)textureObjects unitCount:(GLuint)max
{
// Allocate space for texture object name array
texCount = MIN(max, [textureObjects count]);
if (texCount == 0) return;
textures = malloc(texCount * sizeof *textures);
if (textures == NULL)
{
texCount = 0;
return;
}
// Set up texture object names and appropriate uniforms
unsigned i;
for (i = 0; i != texCount; ++i)
{
[self setUniform:[NSString stringWithFormat:@"tex%u", i] intValue:i];
textureDef = [textureNames objectAtIndex:i];
textures[i] = [OOTexture textureWithConfiguration:textureDef];
if (textures[i] == nil) textures[i] = [OOTexture nullTexture];
textures[i] = [textureObjects objectAtIndex:i];
[textures[i] retain];
}
}

View File

@ -151,10 +151,7 @@ shaderBindingTarget:(id<OOWeakReferenceSupport>)object
if (placeholderMaterial == nil)
{
NSDictionary *materialDefaults = nil;
materialDefaults = [ResourceManager dictionaryFromFilesNamed:@"material-defaults.plist" inFolder:@"Config" andMerge:YES];
placeholderMaterial = [[OOBasicMaterial alloc] initWithName:@"/placeholder/" configuration:[materialDefaults oo_dictionaryForKey:@"no-textures-material"]];
placeholderMaterial = [[OOBasicMaterial alloc] initWithName:@"/placeholder/" configuration:[[ResourceManager materialDefaults] oo_dictionaryForKey:@"no-textures-material"]];
}
return placeholderMaterial;

View File

@ -140,8 +140,7 @@
if (![textureName isEqual:[self textureName]])
{
[_material release];
NSDictionary *spec = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"repeat_s"];
spec = [NSDictionary dictionaryWithObject:spec forKey:@"diffuse_map"];
NSDictionary *spec = [@"{diffuse_map={repeat_s=yes;};}" propertyList];
_material = [[OOSingleTextureMaterial alloc] initWithName:textureName configuration:spec];
}
}

View File

@ -89,6 +89,8 @@ typedef enum
+ (BOOL) writeDiagnosticData:(NSData *)data toFileNamed:(NSString *)name;
+ (NSDictionary *) materialDefaults;
// Clear ResourceManager-internal caches (not those handled by OOCacheManager)
+ (void) clearCaches;

View File

@ -946,6 +946,12 @@ static NSMutableDictionary *sStringCache;
}
+ (NSDictionary *) materialDefaults
{
return [self dictionaryFromFilesNamed:@"material-defaults.plist" inFolder:@"Config" andMerge:YES];
}
+ (BOOL)directoryExists:(NSString *)inPath create:(BOOL)inCreate
{
BOOL exists, directory;