Vuo  0.3
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages

Example: Set up a GL context using Cocoa and run a Vuo image filter.

#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
#import <Cocoa/Cocoa.h>
#import <CoreVideo/CoreVideo.h>
#import <OpenGL/gl.h>
//#import <OpenGL/gl3.h>
#include <OpenGL/glext.h>
#define glGenVertexArrays glGenVertexArraysAPPLE
#define glBindVertexArray glBindVertexArrayAPPLE
#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
#include <OpenGL/CGLCurrent.h>
#include <Vuo/Vuo.h>
#define GLSL_STRING(version,source) "#version " #version "\n" #source
static const char * vertexShaderSource = GLSL_STRING(120,
attribute vec2 position;
varying vec2 texcoord;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
texcoord = position * vec2(0.5) + vec2(0.5);
}
);
static const char * fragmentShaderSource = GLSL_STRING(120,
uniform sampler2D texture;
varying vec2 texcoord;
void main()
{
gl_FragColor = texture2D(texture, texcoord);
}
);
static GLuint compileShader(GLenum type, const char * source)
{
GLint length = strlen(source);
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, (const GLchar**)&source, &length);
glCompileShader(shader);
return shader;
}
static const GLfloat quadPositions[] = { -1, -1, 1, -1, -1, 1, 1, 1 };
static const GLushort quadElements[] = { 0, 1, 2, 3 };
@interface RunImageFilterView : NSOpenGLView
{
VuoRunner * runner;
GLuint vertexArray;
GLuint quadPositionBuffer;
GLuint quadElementBuffer;
GLuint inputTexture;
GLuint vertexShader;
GLuint fragmentShader;
GLuint program;
VuoPublishedPort * inputTexturePort;
GLint positionAttribute;
GLint textureUniform;
}
@end
@implementation RunImageFilterView
- (void)prepareOpenGL
{
// Compile, link, and run the composition
const char *compositionFile = [[[NSBundle mainBundle] pathForResource:@"FrobnicateTexture" ofType:@"vuo"] UTF8String];
runner->start();
// Upload a quad, for rendering the texture later on
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glGenBuffers(1, &quadPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, quadPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadPositions), quadPositions, GL_STATIC_DRAW);
glGenBuffers(1, &quadElementBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadElementBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadElements), quadElements, GL_STATIC_DRAW);
// Share the GL Context with the Vuo Composition
VuoPublishedPort * contextPort = runner->getPublishedInputPortWithName("context");
runner->setPublishedInputPortValue(contextPort, VuoGlContext_stringFromValue(CGLGetCurrentContext()));
// Load an image from disk into a GL Texture
glGenTextures(1,&inputTexture);
glBindTexture(GL_TEXTURE_2D, inputTexture);
NSImage * ni = [NSImage imageNamed:@"OttoOperatesTheRoller.jpg"];
NSImage * niFlipped = [[NSImage alloc] initWithSize:[ni size]];
[niFlipped setFlipped:YES];
[niFlipped lockFocus];
[ni drawInRect:NSMakeRect(0,0,[ni size].width,[ni size].height) fromRect:NSMakeRect(0,0,[ni size].width,[ni size].height) operation:NSCompositeSourceOver fraction:1.0];
[niFlipped unlockFocus];
NSBitmapImageRep * nbir = [NSBitmapImageRep imageRepWithData:[niFlipped TIFFRepresentation]];
glTexImage2D(GL_TEXTURE_2D, 0, 4, [ni size].width, [ni size].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, [nbir bitmapData]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
[niFlipped release];
// Prepare a shader for displaying the GL Texture onscreen
vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
positionAttribute = glGetAttribLocation(program, "position");
textureUniform = glGetUniformLocation(program, "texture");
// Pass the GL Texture to the Vuo Composition
inputTexturePort = runner->getPublishedInputPortWithName("inputTexture");
t.glTextureName = inputTexture;
t.pixelsWide = [ni size].width;
t.pixelsHigh = [ni size].height;
// Call RunImageFilterViewDisplayCallback every vertical refresh
CVDisplayLinkRef displayLink;
CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &displayLink);
CVDisplayLinkSetOutputCallback(displayLink, RunImageFilterViewDisplayCallback, self);
CVDisplayLinkStart(displayLink);
}
CVReturn RunImageFilterViewDisplayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext)
{
RunImageFilterView * view = (RunImageFilterView *)displayLinkContext;
NSAutoreleasePool * p = [[NSAutoreleasePool alloc] init];
[view setNeedsDisplay:YES];
[p drain];
return kCVReturnSuccess;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Execute the Vuo Composition
runner->generatePublishedInputPortEvent(inputTexturePort);
// Retrieve the output GL Texture from the Vuo Composition
VuoPublishedPort * outputTexturePort = runner->getPublishedOutputPortWithName("outputTexture");
VuoGlTexture outputTexture = VuoGlTexture_valueFromString(runner->getPublishedOutputPortValue(outputTexturePort).c_str());
// Display the GL Texture onscreen
glUseProgram(program);
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, outputTexture.glTextureName);
glUniform1i(textureUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, quadPositionBuffer);
glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);
glEnableVertexAttribArray(positionAttribute);
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadElementBuffer);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0);
}
glDisableVertexAttribArray(positionAttribute);
}
glUseProgram(0);
glFlush();
}
@end