mirror of
https://github.com/thes3m/XNI
synced 2024-12-26 13:26:06 +01:00
Added Contains method to GameComponentCollection. Added Support for drawing triangle fans. Added gitignore.
620 lines
20 KiB
Objective-C
620 lines
20 KiB
Objective-C
//
|
|
// GraphicsDevice.m
|
|
// XNI
|
|
//
|
|
// Created by Matej Jan on 27.7.10.
|
|
// Copyright 2010 Retronator. All rights reserved.
|
|
//
|
|
|
|
#import "GraphicsDevice.h"
|
|
#import "GraphicsDevice+Internal.h"
|
|
#import <OpenGLES/ES1/gl.h>
|
|
#import <OpenGLES/ES1/glext.h>
|
|
#import "Retronator.Xni.Framework.h"
|
|
#import "Retronator.Xni.Framework.Graphics.h"
|
|
|
|
#import "XniSamplerEventArgs.h"
|
|
#import "TextureCollection+Internal.h"
|
|
#import "SamplerStateCollection+Internal.h"
|
|
#import "IndexBuffer+Internal.h"
|
|
#import "VertexBuffer+Internal.h"
|
|
#import "RenderTarget2D+Internal.h"
|
|
|
|
@interface GraphicsDevice(){
|
|
BOOL rrt;
|
|
}
|
|
|
|
+ (void) getFormat:(GLenum*)format AndType:(GLenum*)type ForSurfaceFormat:(SurfaceFormat)surfaceFormat;
|
|
- (void) setData:(void*)data size:(int)sizeInBytes toBufferId:(uint)buffer resourceType:(ResourceType)resourceType bufferUsage:(BufferUsage)bufferUsage;
|
|
|
|
@end
|
|
|
|
@implementation GraphicsDevice
|
|
|
|
- (id) initWithGame:(Game*)theGame
|
|
{
|
|
self = [super init];
|
|
if (self)
|
|
{
|
|
game = theGame;
|
|
multisampling = NO;
|
|
|
|
// Create an OpenGL ES context
|
|
context = [self createContext];
|
|
|
|
if (!context || ![EAGLContext setCurrentContext:context]) {
|
|
[self release];
|
|
return nil;
|
|
}
|
|
|
|
if (multisampling) {
|
|
// Create resolve framebuffer object.
|
|
glGenFramebuffers(1, &resolveFramebuffer);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, resolveFramebuffer);
|
|
|
|
// Create resolve color buffer.
|
|
glGenRenderbuffers(1, &resolveRenderbuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, resolveRenderbuffer);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, resolveRenderbuffer);
|
|
}
|
|
|
|
// Create default framebuffer object.
|
|
glGenFramebuffers(1, &defaultFramebuffer);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
|
|
|
|
// Create the color buffer.
|
|
glGenRenderbuffers(1, &colorRenderbuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
|
|
|
|
// Create the depth buffer.
|
|
glGenRenderbuffers(1, &depthRenderbuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
|
|
|
|
// Create sampler states and texture collections and handle changes.
|
|
samplerStates = [[SamplerStateCollection alloc] init];
|
|
textures = [[TextureCollection alloc] init];
|
|
|
|
[samplerStates.samplerStateChanged subscribeDelegate:[Delegate delegateWithTarget:self
|
|
Method:@selector(applySamplerState:eventArgs:)]];
|
|
[textures.textureChanged subscribeDelegate:[Delegate delegateWithTarget:self
|
|
Method:@selector(applySamplerState:eventArgs:)]];
|
|
|
|
// Do the initial reset.
|
|
viewport = [[Viewport alloc] init];
|
|
[self reset];
|
|
|
|
// Initialize defaults.
|
|
self.blendFactor = [Color white];
|
|
self.blendState = [BlendState opaque];
|
|
self.depthStencilState = [DepthStencilState defaultDepth];
|
|
glDepthRangef(0, 1);
|
|
graphicsDeviceStatus = GraphicsDeviceStatusNormal;
|
|
self.indices = nil;
|
|
self.rasterizerState = [RasterizerState cullCounterClockwise];
|
|
self.referenceStencil = 0;
|
|
activeTextureIndex = -1;
|
|
[samplerStates setItem:[SamplerState linearClamp] atIndex:0];
|
|
|
|
// Create events.
|
|
deviceResetting = [[Event alloc] init];
|
|
deviceReset = [[Event alloc] init];
|
|
|
|
vertices = [[NSMutableArray alloc] init];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
#define FLAG_BLOCK(variable, parameter) if (variable) { glEnable(parameter); } else { glDisable(parameter);}
|
|
|
|
@synthesize blendFactor;
|
|
@synthesize blendState;
|
|
- (void) setBlendState:(BlendState*)value {
|
|
if (value != blendState) {
|
|
BlendState *old = blendState;
|
|
blendState = [value retain];
|
|
|
|
// Apply the blend state.
|
|
if (old.colorSourceBlend != blendState.colorSourceBlend ||
|
|
old.colorDestinationBlend != blendState.colorDestinationBlend ||
|
|
old.alphaSourceBlend != blendState.alphaSourceBlend ||
|
|
old.alphaDestinationBlend != blendState.alphaDestinationBlend) {
|
|
|
|
glBlendFuncSeparate(blendState.colorSourceBlend,
|
|
blendState.colorDestinationBlend,
|
|
blendState.alphaSourceBlend,
|
|
blendState.alphaDestinationBlend);
|
|
}
|
|
|
|
if (old.colorBlendFunction != blendState.colorBlendFunction ||
|
|
old.alphaBlendFunction != blendState.alphaBlendFunction) {
|
|
|
|
glBlendEquationSeparate(blendState.colorBlendFunction,
|
|
blendState.alphaBlendFunction);
|
|
}
|
|
|
|
[old release];
|
|
}
|
|
}
|
|
|
|
@synthesize depthStencilState;
|
|
- (void) setDepthStencilState:(DepthStencilState*)value {
|
|
if (value != depthStencilState) {
|
|
DepthStencilState *old = depthStencilState;
|
|
depthStencilState = [value retain];
|
|
|
|
// Apply depth state.
|
|
if (old.depthBufferEnable != depthStencilState.depthBufferEnable) {
|
|
FLAG_BLOCK(depthStencilState.depthBufferEnable, GL_DEPTH_TEST)
|
|
}
|
|
|
|
if (old.depthBufferFunction != depthStencilState.depthBufferFunction) {
|
|
glDepthFunc(depthStencilState.depthBufferFunction);
|
|
}
|
|
|
|
if (old.depthBufferWriteEnable != depthStencilState.depthBufferWriteEnable) {
|
|
glDepthMask(depthStencilState.depthBufferWriteEnable);
|
|
}
|
|
|
|
// TODO: Apply stencil state.
|
|
|
|
[old release];
|
|
}
|
|
}
|
|
|
|
@synthesize graphicsDeviceStatus;
|
|
@synthesize graphicsProfile;
|
|
@synthesize indices;
|
|
@synthesize rasterizerState;
|
|
- (void) setRasterizerState:(RasterizerState*)value {
|
|
if (value != rasterizerState) {
|
|
[value retain];
|
|
[rasterizerState release];
|
|
rasterizerState = value;
|
|
|
|
// Apply fill mode.
|
|
|
|
// Apply cull mode.
|
|
if (value.cullMode == CullModeNone) {
|
|
glDisable(GL_CULL_FACE);
|
|
} else {
|
|
glEnable(GL_CULL_FACE);
|
|
glFrontFace(value.cullMode);
|
|
}
|
|
}
|
|
}
|
|
|
|
@synthesize referenceStencil;
|
|
@synthesize samplerStates;
|
|
@synthesize textures;
|
|
@synthesize viewport;
|
|
|
|
+ (int) getNumberOfVerticesForPrimitiveType:(PrimitiveType)primitiveType primitiveCount:(int)primitiveCount {
|
|
switch (primitiveType) {
|
|
case GL_TRIANGLE_FAN:
|
|
return primitiveCount;
|
|
case PrimitiveTypeLineStrip:
|
|
return primitiveCount + 1;
|
|
case PrimitiveTypeLineList:
|
|
return 2 * primitiveCount;
|
|
case PrimitiveTypeTriangleStrip:
|
|
return primitiveCount + 2;
|
|
case PrimitiveTypeTriangleList:
|
|
return 3 * primitiveCount;
|
|
default:
|
|
[NSException raise:@"NotImplementedException"
|
|
format:@"The primitive type %i is not yet implemented.", primitiveType];
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
@synthesize deviceReset;
|
|
@synthesize deviceResetting;
|
|
|
|
// Presentation
|
|
- (void) reset {
|
|
[deviceResetting raiseWithSender:self];
|
|
|
|
CAEAGLLayer *layer = (CAEAGLLayer*)game.window.handle;
|
|
|
|
if (multisampling) {
|
|
// Allocate resolve buffer backing based on the current layer size.
|
|
glBindFramebuffer(GL_FRAMEBUFFER, resolveFramebuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, resolveRenderbuffer);
|
|
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
|
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
|
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
|
|
NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
|
} else {
|
|
NSLog(@"Created a resolve buffer with dimensions: %ix%i.", backingWidth, backingHeight);
|
|
}
|
|
|
|
// Allocate multisampling buffers based on resolve buffer.
|
|
|
|
// Create default framebuffer object.
|
|
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
|
|
|
|
// Create the color buffer.
|
|
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
|
|
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA8_OES, backingWidth, backingHeight);
|
|
|
|
// Create the depth buffer.
|
|
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
|
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
|
|
NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
|
} else {
|
|
NSLog(@"Created a multisample render target with dimensions: %ix%i.", backingWidth, backingHeight);
|
|
}
|
|
} else {
|
|
// Allocate render buffer backing based on the current layer size.
|
|
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
|
|
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
|
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
|
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
|
|
NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
|
} else {
|
|
NSLog(@"Created a device with dimensions: %ix%i.", backingWidth, backingHeight);
|
|
}
|
|
}
|
|
|
|
// Set viewport.
|
|
glViewport(0, 0, backingWidth, backingHeight);
|
|
self.viewport.x = 0;
|
|
self.viewport.y = 0;
|
|
self.viewport.width = backingWidth;
|
|
self.viewport.height = backingHeight;
|
|
|
|
// Set state defaults.
|
|
glEnable(GL_BLEND);
|
|
|
|
[deviceReset raiseWithSender:self];
|
|
}
|
|
|
|
- (void) present {
|
|
if (multisampling) {
|
|
// Resolve the rendering into the resolve buffer.
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, resolveFramebuffer);
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, defaultFramebuffer);
|
|
glResolveMultisampleFramebufferAPPLE();
|
|
|
|
const GLenum discards[] = {GL_COLOR_ATTACHMENT0,GL_DEPTH_ATTACHMENT};
|
|
glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE,2,discards);
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, resolveRenderbuffer);
|
|
[context presentRenderbuffer:GL_RENDERBUFFER];
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
|
|
} else {
|
|
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
|
|
[context presentRenderbuffer:GL_RENDERBUFFER];
|
|
}
|
|
}
|
|
|
|
// Render buffers
|
|
|
|
- (void) clearWithColor:(Color *)color {
|
|
[self clearWithOptions:ClearOptionsTarget | ClearOptionsDepthBuffer color:color depth:1 stencil:0];
|
|
}
|
|
|
|
- (void) clearWithOptions:(ClearOptions)options color:(Color *)color depth:(float)depth stencil:(int)stencil {
|
|
glDepthMask(GL_TRUE);
|
|
if (color) {
|
|
glClearColor(color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0);
|
|
}
|
|
glClearDepthf(depth);
|
|
glClearStencil(stencil);
|
|
glClear(options);
|
|
glDepthMask(depthStencilState.depthBufferWriteEnable);
|
|
}
|
|
|
|
// Vertex buffers
|
|
- (NSArray*) getVertexBuffers {
|
|
return [NSArray arrayWithArray:vertices];
|
|
}
|
|
|
|
- (void) setVertexBuffer:(VertexBuffer*)vertexBuffer {
|
|
VertexBufferBinding *binding = [[VertexBufferBinding alloc] initWithVertexBuffer:vertexBuffer];
|
|
if ([vertices count]>0) {
|
|
[vertices replaceObjectAtIndex:0 withObject:binding];
|
|
} else {
|
|
[vertices addObject:binding];
|
|
}
|
|
[binding release];
|
|
}
|
|
|
|
- (void) setVertexBuffer:(VertexBuffer*)vertexBuffer vertexOffset:(int)vertexOffset {
|
|
VertexBufferBinding *binding = [[VertexBufferBinding alloc] initWithVertexBuffer:vertexBuffer vertexOffset:vertexOffset];
|
|
[vertices insertObject:binding atIndex:0];
|
|
[binding release];
|
|
}
|
|
|
|
- (void) setVertexBuffers:(VertexBufferBinding*)vertexBuffer, ... {
|
|
if (vertexBuffer != nil) {
|
|
va_list args;
|
|
va_start(args, vertexBuffer);
|
|
VertexBufferBinding *binding = vertexBuffer;
|
|
for (int i = 0; binding; i++) {
|
|
[vertices insertObject:binding atIndex:i];
|
|
binding = va_arg(args, VertexBufferBinding*);
|
|
}
|
|
va_end(args);
|
|
}
|
|
}
|
|
|
|
// Low level methods
|
|
- (uint) createTexture {
|
|
GLuint textureId;
|
|
glGenTextures(1, &textureId);
|
|
return textureId;
|
|
}
|
|
|
|
- (void) releaseTexture:(uint)textureId {
|
|
glDeleteTextures(1, &textureId);
|
|
}
|
|
|
|
- (void) setData:(void*)data toTexture2D:(Texture2D*)texture SourceRectangle:(Rectangle*)rect level:(int)level {
|
|
GLenum format, type;
|
|
[GraphicsDevice getFormat:&format AndType:&type ForSurfaceFormat:texture.format];
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture.textureId);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
if (rect) {
|
|
glTexSubImage2D(GL_TEXTURE_2D, level, rect.x, rect.y, rect.width, rect.height, format, type, data);
|
|
} else {
|
|
glTexImage2D(GL_TEXTURE_2D, level, format, texture.width, texture.height, 0, format, type, data);
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
}
|
|
|
|
- (uint) createBuffer {
|
|
GLuint bufferId;
|
|
glGenBuffers(1, &bufferId);
|
|
return bufferId;
|
|
}
|
|
|
|
- (void) setData:(void*)data toIndexBuffer:(IndexBuffer*)buffer {
|
|
int sizeInBytes = buffer.indexElementSize * buffer.indexCount;
|
|
[self setData:data size:sizeInBytes toBufferId:buffer.bufferID resourceType:ResourceTypeIndexBuffer bufferUsage:buffer.bufferUsage];
|
|
}
|
|
|
|
- (void) setData:(void*)data toVertexBuffer:(VertexBuffer*)buffer {
|
|
int sizeInBytes = buffer.vertexDeclaration.vertexStride * buffer.vertexCount;
|
|
[self setData:data size:sizeInBytes toBufferId:buffer.bufferID resourceType:ResourceTypeVertexBuffer bufferUsage:buffer.bufferUsage];
|
|
}
|
|
|
|
- (void) setData:(void *)data
|
|
size:(int)sizeInBytes
|
|
toBufferId:(uint)buffer
|
|
resourceType:(ResourceType)resourceType
|
|
bufferUsage:(BufferUsage)bufferUsage
|
|
{
|
|
glBindBuffer(resourceType, buffer);
|
|
glBufferData(resourceType, sizeInBytes, data, bufferUsage);
|
|
glBindBuffer(resourceType, 0);
|
|
}
|
|
|
|
- (void)releaseBuffer:(uint)bufferId {
|
|
glDeleteBuffers(1, &bufferId);
|
|
}
|
|
|
|
// Profile specific
|
|
|
|
- (EAGLContext*) createContext { return nil; }
|
|
|
|
- (void) drawPrimitivesOfType:(PrimitiveType)primitiveType
|
|
startVertex:(int)startVertex
|
|
primitiveCount:(int)primitiveCount {}
|
|
|
|
- (void) drawIndexedPrimitivesOfType:(PrimitiveType)primitiveType
|
|
baseVertex:(int)baseVertex
|
|
minVertexIndex:(int)minVertexIndex
|
|
numVertices:(int)numVertices
|
|
startIndex:(int)startIndex
|
|
primitiveCount:(int)primitiveCount {}
|
|
|
|
- (void) drawUserPrimitivesOfType:(PrimitiveType)primitiveType
|
|
vertexData:(VertexArray*)vertexData
|
|
vertexOffset:(int)vertexOffset
|
|
primitiveCount:(int)primitiveCount {}
|
|
|
|
- (void) drawUserPrimitivesOfType:(PrimitiveType)primitiveType
|
|
vertexData:(void*)vertexData
|
|
vertexOffset:(int)vertexOffset
|
|
primitiveCount:(int)primitiveCount
|
|
vertexDeclaration:(VertexDeclaration*) vertexDeclaration {}
|
|
|
|
- (void) drawUserIndexedPrimitivesOfType:(PrimitiveType)primitiveType
|
|
vertexData:(VertexArray*)vertexData
|
|
vertexOffset:(int)vertexOffset
|
|
numVertices:(int)numVertices
|
|
indexData:(IndexArray*)indexData
|
|
indexOffset:(int)indexOffset
|
|
primitiveCount:(int)primitiveCount {}
|
|
|
|
- (void) drawUserIndexedPrimitivesOfType:(PrimitiveType)primitiveType
|
|
vertexData:(void*)vertexData
|
|
vertexOffset:(int)vertexOffset
|
|
numVertices:(int)numVertices
|
|
shortIndexData:(void*)indexData
|
|
indexOffset:(int)indexOffset
|
|
primitiveCount:(int)primitiveCount
|
|
vertexDeclaration:(VertexDeclaration*) vertexDeclaration {}
|
|
// Private methods
|
|
|
|
+ (void) getFormat:(GLenum*)format AndType:(GLenum*)type ForSurfaceFormat:(SurfaceFormat)surfaceFormat {
|
|
switch (surfaceFormat) {
|
|
case SurfaceFormatColor:
|
|
*format = GL_RGBA;
|
|
*type = GL_UNSIGNED_BYTE;
|
|
break;
|
|
case SurfaceFormatAlpha8:
|
|
*format = GL_ALPHA;
|
|
*type = GL_UNSIGNED_BYTE;
|
|
break;
|
|
case SurfaceFormatRgb565:
|
|
*format = GL_RGB;
|
|
*type = GL_UNSIGNED_SHORT_5_6_5;
|
|
break;
|
|
case SurfaceFormatRgba4444:
|
|
*format = GL_RGBA;
|
|
*type = GL_UNSIGNED_SHORT_4_4_4_4;
|
|
break;
|
|
case SurfaceFormatRgba5551:
|
|
*format = GL_RGBA;
|
|
*type = GL_UNSIGNED_SHORT_5_5_5_1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
- (void) applySamplerState:(id)sender eventArgs:(XniSamplerEventArgs*)e {
|
|
if (activeTextureIndex != e.samplerIndex) {
|
|
activeTextureIndex = e.samplerIndex;
|
|
glActiveTexture(GL_TEXTURE0 + e.samplerIndex);
|
|
}
|
|
|
|
Texture *texture = [textures itemAtIndex:e.samplerIndex];
|
|
|
|
if (texture) {
|
|
glBindTexture(GL_TEXTURE_2D, texture.textureId);
|
|
} else {
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
}
|
|
|
|
SamplerState *samplerState = [samplerStates itemAtIndex:e.samplerIndex];
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, samplerState.addressU);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, samplerState.addressV);
|
|
|
|
uint minFilter;
|
|
uint magFilter;
|
|
switch (samplerState.filter) {
|
|
case TextureFilterPoint:
|
|
minFilter = GL_NEAREST;
|
|
magFilter = GL_NEAREST;
|
|
break;
|
|
case TextureFilterLinear:
|
|
default:
|
|
minFilter = GL_LINEAR;
|
|
magFilter = GL_LINEAR;
|
|
break;
|
|
case TextureFilterPointMipLinear:
|
|
minFilter = GL_NEAREST_MIPMAP_LINEAR;
|
|
magFilter = GL_NEAREST_MIPMAP_LINEAR;
|
|
break;
|
|
case TextureFilterLinearMipPoint:
|
|
minFilter = GL_LINEAR_MIPMAP_NEAREST;
|
|
magFilter = GL_LINEAR_MIPMAP_NEAREST;
|
|
break;
|
|
case TextureFilterMinLinearMagPointMipLinear:
|
|
minFilter = GL_LINEAR;
|
|
magFilter = GL_NEAREST_MIPMAP_LINEAR;
|
|
break;
|
|
case TextureFilterMinLinearMagPointMipPoint:
|
|
minFilter = GL_LINEAR_MIPMAP_NEAREST;
|
|
magFilter = GL_NEAREST;
|
|
break;
|
|
case TextureFilterMinPointMagLinearMipLinear:
|
|
minFilter = GL_NEAREST_MIPMAP_LINEAR;
|
|
magFilter = GL_LINEAR;
|
|
break;
|
|
case TextureFilterMinPointMagLinearMipPoint:
|
|
minFilter = GL_NEAREST;
|
|
magFilter = GL_LINEAR_MIPMAP_NEAREST;
|
|
break;
|
|
case TextureFilterAnisotropic:
|
|
// TODO: Have no idea yet how to do anisotropic.
|
|
minFilter = GL_LINEAR;
|
|
magFilter = GL_LINEAR;
|
|
break;
|
|
}
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
|
|
}
|
|
|
|
- (void) setRenderTarget:(RenderTarget2D*)renderTarget{
|
|
GLenum format, type;
|
|
|
|
if (renderTarget == nil) {
|
|
if (rrt) {
|
|
//We had render target before now we have to flip it vertically
|
|
rrt = NO;
|
|
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
|
|
}
|
|
|
|
}else{
|
|
GLuint rtFramebuffer = [renderTarget colorFramebuffer];
|
|
|
|
[GraphicsDevice getFormat:&format AndType:&type ForSurfaceFormat:renderTarget.format];
|
|
|
|
// RENDER TO TEXTURE BUFFER
|
|
// This is the buffer we will be rendering to and using as a texture
|
|
// on out screen plane
|
|
glBindFramebufferOES(GL_FRAMEBUFFER_OES, rtFramebuffer);
|
|
|
|
// create the texture object
|
|
glBindTexture(GL_TEXTURE_2D, renderTarget.textureId);
|
|
|
|
// set the texture parameter filtering (feel free to use other TexParams)
|
|
// you have to do this, forgetting to do this will make it not work.
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
|
|
|
// fill the texture data (the max texture size needs to be power of 2)
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderTarget.width, renderTarget.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
// attach the frameBuffer to the texture object
|
|
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, renderTarget.textureId, 0);
|
|
|
|
//glOrthof(0, renderTarget.width, renderTarget.height, 0, -1, 1);
|
|
|
|
// CHECK FRAME BUFFER STATUS HERE
|
|
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER);
|
|
|
|
if(status != GL_FRAMEBUFFER_COMPLETE){
|
|
NSLog(@"Error binding renderTarget");
|
|
}
|
|
|
|
rrt = YES;
|
|
}
|
|
}
|
|
|
|
- (RenderTarget2D*) getRenderTarget{
|
|
return nil;
|
|
}
|
|
|
|
- (void) dealloc{
|
|
[blendState release];
|
|
[depthStencilState release];
|
|
[rasterizerState release];
|
|
[samplerStates release];
|
|
[textures release];
|
|
[viewport release];
|
|
[deviceResetting release];
|
|
[deviceReset release];
|
|
[vertices release];
|
|
[super dealloc];
|
|
}
|
|
|
|
|
|
|
|
@end
|