Sources/GLQuad.mm
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Utility class for rendering a textured quad. |
*/ |
#import <iostream> |
#import <OpenGL/gl3.h> |
#import "GLShader.h" |
#import "GLProgram.h" |
#import "GLQuad.h" |
enum : long |
{ |
eGLAttributeVertex, |
eGLAttributeTexCoords, |
eGLAttributeCount |
}; |
static const GLsizei kGLSizeFloat = sizeof(GLfloat); |
// Get the buffer offset |
static GLchar* GLUBufferOffset(const GLintptr& nOffset) |
{ |
return((GLchar *)nullptr + nOffset); |
} // GLUBufferOffset |
@implementation GLQuad |
{ |
@private |
BOOL _bind; |
GLenum _mode; |
GLenum _target; |
GLuint _pid; |
GLuint _vao; |
NSRect _bounds; |
NSSize _size; |
BOOL isTexture2D; |
GLuint vbo; |
GLProgram* program; |
} |
- (GLProgram*) _newProgram |
{ |
GLProgram* aProgram = nil; |
NSString* rsrc = (_target == GL_TEXTURE_2D) ? @"Quad2D" : @"QuadRect"; |
// Create a vertex shader |
GLShader* vertex = [GLShader shaderWithResource:rsrc |
type:GL_VERTEX_SHADER]; |
if(vertex) |
{ |
// Create a fragment shader |
GLShader* fragment = [GLShader shaderWithResource:rsrc |
type:GL_FRAGMENT_SHADER]; |
if(fragment) |
{ |
aProgram = [GLProgram new]; |
if(aProgram) |
{ |
aProgram.shader = vertex.shader; |
aProgram.shader = fragment.shader; |
aProgram.attribute = "vertex"; |
aProgram.attribute = "texCoord"; |
if(![aProgram link]) |
{ |
[aProgram release]; |
} // if |
} // if |
} // if |
} // if |
return aProgram; |
} // _newProgram |
- (void) _acquireVAO |
{ |
// Create a vertex array |
glGenVertexArrays(1, &_vao); |
glBindVertexArray(_vao); |
GLfloat s = GLfloat(_size.width); |
GLfloat t = GLfloat(_size.height); |
GLfloat data[] = |
{// x y s t |
-1.0, -1.0, 0.0, t, |
-1.0, 1.0, 0.0, 0.0, |
1.0, -1.0, s, t, |
1.0, 1.0, s, 0.0 |
}; |
glGenBuffers(1, &vbo); |
glBindBuffer(GL_ARRAY_BUFFER, vbo); |
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); |
GLsizei stride = 4 * kGLSizeFloat; |
// Vertices |
glVertexAttribPointer(eGLAttributeVertex, 2, GL_FLOAT, GL_FALSE, stride, GLUBufferOffset(0)); |
// Texture coordinates |
glVertexAttribPointer(eGLAttributeTexCoords, 2, GL_FLOAT, GL_FALSE, stride, GLUBufferOffset(2 * kGLSizeFloat)); |
} // _acquireVAO |
- (void) _acquireQuad:(const NSRect)bounds |
{ |
// Set the quad bounds |
_bounds = bounds; |
// Is this a quad for texture 2D? |
isTexture2D = (_size.width == 1.0) && (_size.height == 1.0); |
// Texture target |
_target = (isTexture2D) ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE; |
// Draw Mode |
_mode = GL_TRIANGLE_STRIP; |
// Create a _program object for shaders |
program = [self _newProgram]; |
if(program) |
{ |
// Get the program id |
_pid = program.pid; |
} // if |
} // _acquireQuad |
- (nullable instancetype) init |
{ |
self = [super init]; |
if(self) |
{ |
NSSize size = NSMakeSize(1.0, 1.0); |
NSRect bounds = NSMakeRect(0.0, 0.0, size.width, size.height); |
_size = size; |
[self _acquireQuad:bounds]; |
[self _acquireVAO]; |
} // if |
return self; |
} // init |
// Create a quad with the bounds |
- (nullable instancetype) initWithBounds:(const NSRect)bounds |
{ |
self = [super init]; |
if(self) |
{ |
[self _acquireQuad:bounds]; |
} // if |
return self; |
} // initWithSize |
// Destructor |
- (void) dealloc |
{ |
glDeleteBuffers(1, &vbo); |
glDeleteVertexArrays(1,&_vao); |
if(program) |
{ |
[program release]; |
} // if |
[super dealloc]; |
} // dealloc |
// Set the image size. For texture 2D the default coordinates are used. |
// For texture rectangle you need to set the original image size. |
- (void) setSize:(NSSize)size |
{ |
if(!isTexture2D && ((size.width != _size.width) && (size.height != _size.height))) |
{ |
// Set the image size |
_size = size; |
// Create a new vao for the texture rectangle |
[self _acquireVAO]; |
} // if |
} // setSize |
// Render the textured quad |
- (void) render:(const GLuint)texture |
{ |
if(texture) |
{ |
glUseProgram(_pid); |
{ |
glEnable(_target); |
{ |
glBindTexture(_target, texture); |
{ |
glBindVertexArray(_vao); |
glEnableVertexAttribArray(eGLAttributeVertex); |
glEnableVertexAttribArray(eGLAttributeTexCoords); |
glDrawArrays(_mode, 0, 4); |
glDisableVertexAttribArray(eGLAttributeTexCoords); |
glDisableVertexAttribArray(eGLAttributeVertex); |
} |
glBindTexture(_target, 0); |
} |
glDisable(_target); |
} |
glUseProgram(0); |
} // if |
} // render |
@end |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-12-10