Sources/Toolkits/Classes/OpenGLFilterUtilityToolkit.m
//--------------------------------------------------------------------------- |
// |
// File: OpenGLFilterUtilityToolKit.m |
// |
// Portions derived from the work authored by Mark J. Harris |
// and Mike Weiblen. |
// |
// Abstract: Utility class for installing an image processing filter |
// |
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
// Computer, Inc. ("Apple") in consideration of your agreement to the |
// following terms, and your use, installation, modification or |
// redistribution of this Apple software constitutes acceptance of these |
// terms. If you do not agree with these terms, please do not use, |
// install, modify or redistribute this Apple software. |
// |
// In consideration of your agreement to abide by the following terms, and |
// subject to these terms, Apple grants you a personal, non-exclusive |
// license, under Apple's copyrights in this original Apple software (the |
// "Apple Software"), to use, reproduce, modify and redistribute the Apple |
// Software, with or without modifications, in source and/or binary forms; |
// provided that if you redistribute the Apple Software in its entirety and |
// without modifications, you must retain this notice and the following |
// text and disclaimers in all such redistributions of the Apple Software. |
// Neither the name, trademarks, service marks or logos of Apple Computer, |
// Inc. may be used to endorse or promote products derived from the Apple |
// Software without specific prior written permission from Apple. Except |
// as expressly stated in this notice, no other rights or licenses, express |
// or implied, are granted by Apple herein, including but not limited to |
// any patent rights that may be infringed by your derivative works or by |
// other works in which the Apple Software may be incorporated. |
// |
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
// |
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
// POSSIBILITY OF SUCH DAMAGE. |
// |
// Copyright (c) 2008 Apple Inc., All rights reserved. |
// |
//--------------------------------------------------------------------------- |
//------------------------------------------------------------------------ |
#import <OpenGL/gl.h> |
#import <OpenGL/OpenGL.h> |
#import "OpenGLFilterUtilityToolkit.h" |
//------------------------------------------------------------------------ |
//------------------------------------------------------------------------ |
struct FilterAttributes |
{ |
GLint *uniformLocation; // Texture unit in this case |
GLint uniformValue; // The uniform initial value |
GLdouble orth2DRange[4]; // Frame for 2D orthographic projection matrix |
}; |
typedef struct FilterAttributes FilterAttributes; |
//------------------------------------------------------------------------ |
//------------------------------------------------------------------------ |
@implementation OpenGLFilterUtilityToolKit |
//------------------------------------------------------------------------ |
#pragma mark -- Kernel Utilities -- |
//------------------------------------------------------------------------ |
- (void) setUniformValue:(NSDictionary *)theUniformDictionary uniformKeys:(NSArray *)theUniformKeys |
{ |
NSString *theUniformKey = [theUniformKeys objectAtIndex:0]; |
if ( theUniformKey ) |
{ |
NSNumber *theUniformNumber = [theUniformDictionary objectForKey:theUniformKey]; |
if ( theUniformNumber ) |
{ |
filterAttributes->uniformValue = [theUniformNumber integerValue]; |
// Identify the bound texture unit as input to the filter |
// For details on glUniform1iARB refer to: |
// |
// http://developer.3dlabs.com/openGL2/slapi/UniformARB.htm |
glUniform1iARB( filterAttributes->uniformLocation[0], |
filterAttributes->uniformValue ); |
} // if |
} // if |
} // setUniformValue |
//------------------------------------------------------------------------ |
#pragma mark -- Initializing a new filter -- |
//------------------------------------------------------------------------ |
- (void) initComputationalKernel:(NSString *)theFilterName |
uniformDictionary:(NSDictionary *)theUniformDictionary |
bounds:(NSRect)theBounds |
{ |
// If one has a uniform associated with a fragment shader |
// initiliaze its dictionary here |
NSArray *theUniformKeys = [theUniformDictionary allKeys]; |
if ( theUniformKeys ) |
{ |
// Compile, link and get a program object |
kernel = [[OpenGLFragmentShaderUtilityToolkit alloc] initWithFragmentShaderInAppBundle:theFilterName |
uniformKeys:theUniformKeys |
bounds:theBounds]; |
if ( kernel ) |
{ |
// Once the fragment shader has been compiled, linked and |
// bound to a program object, cache the uniform location. |
filterAttributes->uniformLocation = [kernel uniformLocation]; |
[kernel enable]; |
[self setUniformValue:theUniformDictionary uniformKeys:theUniformKeys]; |
[kernel disable]; |
} // if |
} // if |
} // initComputationalKernel |
//------------------------------------------------------------------------ |
- (void) initOrth2DRange:(NSRect)theBounds |
{ |
filterAttributes->orth2DRange[0] = theBounds.origin.x; // left |
filterAttributes->orth2DRange[1] = theBounds.size.width; // right |
filterAttributes->orth2DRange[2] = theBounds.origin.y; // bottom |
filterAttributes->orth2DRange[3] = theBounds.size.height; // top |
} // initOrth2DRange |
//------------------------------------------------------------------------ |
- (void) initFilterAttributes |
{ |
filterAttributes = (FilterAttributesRef)malloc( sizeof( FilterAttributes ) ); |
if ( filterAttributes != NULL ) |
{ |
filterAttributes->uniformLocation = NULL; |
filterAttributes->uniformValue = 0; |
filterAttributes->orth2DRange[0] = 0; |
filterAttributes->orth2DRange[1] = 0; |
filterAttributes->orth2DRange[2] = 0; |
filterAttributes->orth2DRange[3] = 0; |
} // if |
} // initFilterAttributes |
//------------------------------------------------------------------------ |
- (id) initWithFilterInAppBundle:(NSString *)theFilterName |
uniformDictionary:(NSDictionary *)theUniformDictionary |
bounds:(NSRect)theBounds |
size:(NSSize)theSize |
{ |
if ( theFilterName ) |
{ |
[self initFilterAttributes]; |
if ( filterAttributes != NULL ) |
{ |
// Framebuffer object is initialized here |
fbo = [[OpenGLFBOUtilityToolKit alloc] initWithTextureSize:theSize bounds:theBounds]; |
// Fragment shader is initialized here |
[self initComputationalKernel:theFilterName uniformDictionary:theUniformDictionary bounds:theBounds]; |
// Map the domain values into 2D range used for orthographic |
// projection matrix |
[self initOrth2DRange:theBounds]; |
} // if |
} // if |
return self; |
} // initWithFilterInAppBundle |
//------------------------------------------------------------------------ |
#pragma mark -- Deleting the filter -- |
//------------------------------------------------------------------------ |
- (void) deallocFilterAttributes |
{ |
// Delete filter resources |
if ( filterAttributes != NULL ) |
{ |
free( filterAttributes ); |
} // if |
filterAttributes = NULL; |
} // deallocFilterAttributes |
//------------------------------------------------------------------------ |
- (void) dealloc |
{ |
// The FBO is no longer needed |
[fbo dealloc]; |
// The fragment shader is not needed |
[kernel dealloc]; |
// Delete the filter opaque data reference |
[self deallocFilterAttributes]; |
[super dealloc]; |
} // dealloc |
//------------------------------------------------------------------------ |
#pragma mark -- Utility routine for filter application -- |
//------------------------------------------------------------------------ |
// |
// Here we shall demonstrate one-to-one pixel to texel mapping via the |
// use of a data-dimensioned viewport. Namely, we need a one-to-one |
// mapping of pixels to texels in order to ensure every element of our |
// texture is processed. By setting our viewport to the dimensions of |
// our destination texture and drawing a screen-sized quad, we ensure |
// that every pixel of our texel is generated and processed in the |
// fragment program. |
// |
//------------------------------------------------------------------------ |
- (void) prepare |
{ |
// Bind to the FBO and draw into it and set the viewport to |
// the dimensions of our texture |
[fbo bind]; |
// Initialize some states before rendering a geometry/model |
glClear( GL_COLOR_BUFFER_BIT ); |
glMatrixMode( GL_MODELVIEW ); |
// After this stage, one would normally feed data into a filter |
// by, for example, rendering some 3D models |
} // prepare |
//------------------------------------------------------------------------ |
// |
// This method updates the texture by rendering a geometry, or a model, |
// and then copying the rendered image to a texture. During a second |
// rendering pass, the same geometry, or the model, is re-rendered using |
// the texture as input to a filter. Lastly, the output from the filter |
// are copied to the texture. The texture can now be used for displaying |
// the results. |
// |
//------------------------------------------------------------------------ |
-(void) run |
{ |
// Copy the results to the FBO bound texture |
[fbo draw]; |
// Execute the computational kernel |
[kernel execute]; |
// Display the results |
[fbo unbind]; |
} // updateView |
//------------------------------------------------------------------------ |
// |
// Properly set the viewport bounds |
// |
//------------------------------------------------------------------------ |
- (void) setViewport:(NSRect)theBounds |
{ |
GLsizei theWidth = (GLsizei)theBounds.size.width; |
GLsizei theHeight = (GLsizei)theBounds.size.height; |
if ( theHeight == 0 ) |
{ |
theHeight = 1; |
} //if |
glViewport( 0, 0, theWidth, theHeight ); |
} // setViewport |
//------------------------------------------------------------------------ |
// |
// To demonstrate the concept of a one-to-one mapping of pixels to texels, |
// here we shall set the projection matrix to orthographic, in a closed |
// domain with bounds of [X,Y'] in the coordinate system with dimensions |
// determined by {x,y}. |
// |
//------------------------------------------------------------------------ |
- (void) mapPixelsToTexels |
{ |
glMatrixMode( GL_PROJECTION ); |
glLoadIdentity( ); |
gluOrtho2D( filterAttributes->orth2DRange[0], |
filterAttributes->orth2DRange[1], |
filterAttributes->orth2DRange[2], |
filterAttributes->orth2DRange[3] ); |
glMatrixMode( GL_MODELVIEW ); |
glLoadIdentity( ); |
} // mapPixelsToTexels |
//------------------------------------------------------------------------ |
// |
// Our data domain here is defined by |
// |
// D = { [X,Y]x[X',Y'] } |
// |
// where |
// |
// [X,Y] represents the origin, |
// |
// [X',Y'] represents the coordinates defined by X'=X+W |
// and the Y'=Y+H, with W=Width and H=Height. |
// |
// Here we shall set the frustum to orthographic, and the frustum |
// dimensions to [X,Y']. Hence, our viewport-sized quad vertices |
// becomes the corners of the viewport or |
// |
// [X,Y'] [X',Y'] |
// +-------------------+ |
// | | |
// | | |
// | | |
// +-------------------+ |
// [X,Y] [X',Y] |
// |
//------------------------------------------------------------------------ |
- (void) resize:(NSRect)theBounds |
{ |
// Properly resize the viewport |
[self setViewport:theBounds]; |
// One-to-one Pixel to texel mapping using an orthographic |
// projection matrix |
[self mapPixelsToTexels]; |
} // resize |
//------------------------------------------------------------------------ |
//------------------------------------------------------------------------ |
@end |
//------------------------------------------------------------------------ |
//------------------------------------------------------------------------ |
Copyright © 2008 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2008-02-06