首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL游戏编辑视图

OpenGL游戏编辑视图
EN

Code Review用户
提问于 2011-08-14 19:36:14
回答 1查看 687关注 0票数 5

我正在做一个使用OpenGL的可可项目。我试图让事情变得容易跨平台以便以后(这是我的GL单例的主要原因;我希望实现目前使用NSOpenGL...NSOpenGL...方法的Linux版本)。然而,当我做可可和OpenGL的事情时,我从来不确定我是以“正确”的方式做事情的。我还能在这里做更好的事吗?我删掉了与GL或绘图无关的方法。

下面是我的NSView子类:

代码语言:javascript
复制
//
//  IRLevelViewView
//  Iris
//
//  Created by Andy Van Ness on 3/15/11.
//  Copyright 2011 Andy Van Ness. All rights reserved.
//

#import "IRGameEditView.h"
#import <OpenGL/gl.h>
#import "IRGL.h"
//snip

@implementation IRGameEditView

- (id)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    if (self != nil)
    {
        //snip

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(surfaceNeedsUpdate:) name:NSViewGlobalFrameDidChangeNotification object:self];
    }
    return self;
}

- (void)initDisplayLink
{
    GLint swapInt = 1;
    [[[IRGL gl] glContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; 

    CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
    CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);

    CGLContextObj cglContext = [[[IRGL gl] glContext] CGLContextObj];
    CGLPixelFormatObj cglPixelFormat = [[NSOpenGLView defaultPixelFormat] CGLPixelFormatObj];
    CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);

    CVDisplayLinkStart(displayLink);
}

- (void)initGL
{   
    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);

    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    [[IRGL gl] initShaders];
    [self reshape];

    [self setReadyForGL:YES];
}

static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
    NSAutoreleasePool* pool = [NSAutoreleasePool new];

    [(id)displayLinkContext setNeedsDisplay:YES];

    [pool drain];

    return kCVReturnSuccess;
}

- (void)lockFocus
{
    [super lockFocus];
    [[IRGL gl] activateContextForView:self];
}

- (void)drawRect:(NSRect)dirtyRect
{
    if (![self isReadyForGL]) [self initGL];

    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    [[self clock] updateTime];
    CGFloat animator = (CGFloat)([[self clock] time] % 100000)/100000.0;

    [[IRGL gl] setCurrentShader:IRIrisShader];
    [[IRGL gl] setUniformGLVariable:@"animator" toFloat:animator];
    [[IRGL gl] setUniformGLVariable:@"cameraCenter" toPoint:[[self camera] center]];
    [[IRGL gl] setUniformGLVariable:@"cameraTileAspectRatio" toFloat:[[self camera] tileAspectRatio]];
    [[IRGL gl] setUniformGLVariable:@"cameraZoom" toFloat:[[self camera] zoom]];
    [[IRGL gl] setUniformGLVariable:@"cameraSize" toSize:[[self camera] size]];
    [[self camera] loadCameraMatrix];

    @synchronized([[self level] tileMap])
    {
        for (IRTileStack* currentStack in [[[self level] tileMap] tileStacksInIrisRect:[[self camera] irisFrame]])
        {
            [currentStack draw];
        }
    }

    glFlush();
}

- (void)reshape
{
    glViewport(0, 0, (GLsizei)[self frame].size.width, (GLsizei)[self frame].size.height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, [self frame].size.width, [self frame].size.height, 0, -2, 0);

    glMatrixMode(GL_MODELVIEW);
}

- (BOOL)isOpaque  { return YES; }
- (BOOL)isFlipped { return YES; }

- (void)setFrame:(NSRect)frameRect
{
    [super setFrame:frameRect];

    [[IRGL gl] activateContextForView:self];
    [self reshape];

    [self setNeedsDisplay:YES];
}

@synthesize automaticallyRedraws;
- (void)setAutomaticallyRedraws:(BOOL)newAutomaticallyRedraws
{
    if (newAutomaticallyRedraws != automaticallyRedraws)
    {
        automaticallyRedraws = newAutomaticallyRedraws;
        if (automaticallyRedraws)
        {
            [self initDisplayLink];
        }
        else
        {
            CVDisplayLinkRelease(displayLink);
        }
    }
}

- (void)surfaceNeedsUpdate:(NSNotification*)notification
{
    [[[IRGL gl] glContext] update];
}

//snip

@end

下面是一个单例GL类:

代码语言:javascript
复制
//
//  IRGL.m
//  Iris
//
//  Created by Andy Van Ness on 8/9/11.
//  Copyright 2011 Andy Van Ness. All rights reserved.
//

#import "IRGL.h"

@implementation IRGL

//snip

@synthesize currentShader;
- (void)setCurrentShader:(NSString *)newCurrentShader
{
    if (![currentShader isEqualToString:newCurrentShader])
    {
        [currentShader release];
        currentShader = [newCurrentShader copy];
    }

    if (!newCurrentShader)
    {
        glUseProgramObjectARB(0);
    }
    else
    {
        glUseProgramObjectARB([self shaderForKey:currentShader]);
    }
}

- (void)initShaders
{
    for (NSString* currentID in [NSArray arrayWithObjects:IRAllShaders])
    {
        [self addShaderWithID:currentID];
    }

    [self setInitialized:YES];
}

- (void)addShaderWithID:(NSString*)key
{
    NSString* shaderSource = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:key ofType:@"fs"] encoding:NSUTF8StringEncoding error:nil];

    if ([shaderSource length] > 0)
    {
        GLhandleARB shaderProgram = glCreateProgramObjectARB();

        GLchar const* source = [shaderSource UTF8String];
        GLint const length = [shaderSource length];
        GLhandleARB shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
        glShaderSourceARB(shader, 1, &source, &length);

        glCompileShaderARB(shader);
        glAttachObjectARB(shaderProgram, shader);

        glLinkProgramARB(shaderProgram);
        MOGLShaderInfoLog(shaderProgram);

        [[self shaders] setObject:[NSValue valueWithPointer:shaderProgram] forKey:key];
        [[self uniformVariablesByShader] setObject:[NSMutableDictionary dictionary] forKey:key];
    }
    else
    {
        MOLogWarning(@"Shader not found.");
    }
}

- (GLhandleARB)shaderForKey:(NSString *)shaderKey
{
    if (shaderKey == nil) return 0;

    NSValue* shaderValue = [[self shaders] objectForKey:shaderKey];

    if (!shaderValue) MOLogError(@"Shader %@ not found.",shaderKey);

    return [shaderValue pointerValue];
}

- (GLint)uniformLocationForName:(NSString*)varName
{
    NSNumber* uniformLocation = [[[self uniformVariablesByShader] objectForKey:[self currentShader]] objectForKey:varName];

    if (!uniformLocation)
    {
        GLint var = glGetUniformLocationARB([self shaderForKey:[self currentShader]],[varName UTF8String]);
        uniformLocation = [NSNumber numberWithInteger:var];
        MOGLError();
        if (var == -1)
        {
            MOLogError(@"Uniform %@ could not be found.",varName);
        }
        else
        {
            [[[self uniformVariablesByShader] objectForKey:[self currentShader]] setObject:uniformLocation forKey:varName]; 
        }
    }

    return (GLint)[uniformLocation integerValue];
}

- (void)setUniformGLVariable:(NSString*)varName toFloat:(CGFloat)varValue
{
    if ([self isInitialized])
    {
        glUniform1f([self uniformLocationForName:varName], varValue);
        MOGLError();
    }
}

//snip; bunches more methods like that one

- (void)activateContext
{
    if (![self glContext])
    {
        NSOpenGLContext* newContext = [[NSOpenGLContext alloc] initWithFormat:[NSOpenGLView defaultPixelFormat] shareContext:nil];
        [self setGLContext:newContext];
        [newContext release];
        MOGLError();
    }

    [[self glContext] makeCurrentContext];
    MOGLError();
}

- (void)activateContextForView:(NSView*)view
{
    [self activateContext];
    [[self glContext] setView:view];
}

@end
EN

回答 1

Code Review用户

回答已采纳

发布于 2011-12-04 07:43:11

  1. CVDisplayLink是异步的,一般来说,AppKit不是线程安全。
  2. 使用setNeedsDisplay (它在将来的某个时候为您提供刷新),在绘图回调中将忽略显示链接的点,该链接正在绘制与屏幕刷新同步的内容。
  3. 你可以放下ARB,对吧?快到2012年了。
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/4093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档