// // BasicEffect.m // XNI // // Created by Matej Jan on 21.9.10. // Copyright 2010 Retronator. All rights reserved. // #import "BasicEffect.h" #import "Retronator.Xni.Framework.h" #import "Retronator.Xni.Framework.Graphics.h" @interface BasicEffectPass : EffectPass { BasicEffect *basicEffect; ReachGraphicsDevice *reachGraphicsDevice; } - (id) initWithBasicEffect:(BasicEffect*)theBasicEffect graphicsDevice:(GraphicsDevice*)theGraphicsDevice; @end @implementation BasicEffect -(id) initWithGraphicsDevice:(GraphicsDevice *)theGraphicsDevice { self = [super initWithGraphicsDevice:theGraphicsDevice]; if (self) { // Create the main pass. BasicEffectPass *mainPass = [[[BasicEffectPass alloc] initWithBasicEffect:self graphicsDevice:graphicsDevice] autorelease]; NSArray *passes = [NSArray arrayWithObject:mainPass]; // Create the basic technique. EffectTechnique *basicTechnique = [[[EffectTechnique alloc] initWithName:@"BasicEffect" passes:passes] autorelease]; techniques = [[NSDictionary alloc] initWithObjectsAndKeys:basicTechnique, basicTechnique.name, nil]; currentTechnique = basicTechnique; // Set defaults. self.alpha = 1; self.ambientColor = [Vector3 zero]; self.diffuseColor = [Vector3 zero]; self.emissiveColor = [Vector3 zero]; self.specularColor = [Vector3 zero]; self.specularPower = 0; self.vertexColorEnabled = NO; self.textureEnabled = NO; self.texture = nil; self.lightingEnabled = NO; self.ambientLightColor = [Vector3 zero]; directionalLight0 = [[DirectionalLight alloc] init]; directionalLight1 = [[DirectionalLight alloc] init]; directionalLight2 = [[DirectionalLight alloc] init]; self.fogEnabled = NO; self.fogColor = [Vector3 zero]; self.fogStart = 0; self.fogEnd = 1; self.projection = [Matrix identity]; self.view = [Matrix identity]; self.world = [Matrix identity]; } return self; } @synthesize alpha; @synthesize ambientColor; @synthesize diffuseColor; @synthesize emissiveColor; @synthesize specularColor; @synthesize specularPower; @synthesize vertexColorEnabled; @synthesize textureEnabled; @synthesize texture; @synthesize lightingEnabled; @synthesize ambientLightColor; @synthesize directionalLight0; @synthesize directionalLight1; @synthesize directionalLight2; @synthesize fogEnabled; @synthesize fogColor; @synthesize fogStart; @synthesize fogEnd; @synthesize projection; @synthesize view; @synthesize world; - (void) dealloc { [ambientColor release]; [diffuseColor release]; [emissiveColor release]; [specularColor release]; [texture release]; [ambientLightColor release]; [directionalLight0 release]; [directionalLight1 release]; [directionalLight2 release]; [fogColor release]; [world release]; [view release]; [projection release]; [techniques release]; [super dealloc]; } @end @interface BasicEffectPass() - (void) activateLight:(DirectionalLight*) light name:(uint)name; @end @implementation BasicEffectPass - (id) initWithBasicEffect:(BasicEffect *)theBasicEffect graphicsDevice:(GraphicsDevice*)theGraphicsDevice { self = [super initWithName:@"BasicEffectPass" graphicsDevice:theGraphicsDevice]; if (self) { basicEffect = theBasicEffect; reachGraphicsDevice = (ReachGraphicsDevice*)theGraphicsDevice; } return self; } - (void) apply { // Set material. Vector4Struct data; Vector4Set(&data, basicEffect.ambientColor.x, basicEffect.ambientColor.y, basicEffect.ambientColor.z, basicEffect.alpha); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&data); Vector4Set(&data, basicEffect.diffuseColor.x, basicEffect.diffuseColor.y, basicEffect.diffuseColor.z, basicEffect.alpha); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&data); Vector4Set(&data, basicEffect.specularColor.x, basicEffect.specularColor.y, basicEffect.specularColor.z, 1); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&data); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, basicEffect.specularPower); Vector4Set(&data, basicEffect.emissiveColor.x, basicEffect.emissiveColor.y, basicEffect.emissiveColor.z, 1); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&data); if (basicEffect.vertexColorEnabled) { glEnable(GL_COLOR_MATERIAL); } else { glDisable(GL_COLOR_MATERIAL); } // Set texturing. if (basicEffect.textureEnabled) { [graphicsDevice.textures setItem:basicEffect.texture atIndex:0]; //glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); } else { glDisable(GL_TEXTURE_2D); } // Set the projection matrix. glMatrixMode(GL_PROJECTION); glLoadMatrixf((float*)basicEffect.projection.data); // Set the model-view matrix. glMatrixMode(GL_MODELVIEW); // Multiply in reverse order, because our matrices assume vector transformation b = a * M, // while openGL will tranform b = M * a. So v_projectionspace = M_modelview * v_modelspace, // and our model-view matrix therefore should be view * world. glLoadMatrixf((float*)basicEffect.view.data); // Set lighting now that we're in view coordinates. if (basicEffect.lightingEnabled) { glEnable(GL_LIGHTING); } else { glDisable(GL_LIGHTING); } Vector4Set(&data, basicEffect.ambientLightColor.x, basicEffect.ambientLightColor.y, basicEffect.ambientLightColor.z, 1); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float*)&data); [self activateLight:basicEffect.directionalLight0 name:GL_LIGHT0]; [self activateLight:basicEffect.directionalLight1 name:GL_LIGHT1]; [self activateLight:basicEffect.directionalLight2 name:GL_LIGHT2]; // Finally add the world component of the model-view matrix. glMultMatrixf((float*)basicEffect.world.data); } - (void) activateLight:(DirectionalLight *)light name:(uint)lightName { [reachGraphicsDevice setLight:lightName to:light.enabled]; if (!light.enabled) { return; } Vector4Struct data; Vector4Set(&data, light.diffuseColor.x, light.diffuseColor.y, light.diffuseColor.z, 1); glLightfv(lightName, GL_DIFFUSE, (float*)&data); Vector4Set(&data, light.specularColor.x, light.specularColor.y, light.specularColor.z, 1); glLightfv(lightName, GL_SPECULAR, (float*)&data); Vector4Set(&data, -light.direction.x, -light.direction.y, -light.direction.z, 0); glLightfv(lightName, GL_POSITION, (float*)&data); } @end