I'm trying to get the bytes from a RGBA texture in openGL ES. I think I'm trying to imitate glGetTexImage from vanilla openGL. As is right now, the pixels are all nil, from the call to glClear, not the texture data I'm looking for.
This is a method in a category extending SPTexture from Sparrow Framework.
-(NSMutableData *) getPixelsFromTexture
{
GLsizei width = (GLsizei) self.width;
GLsizei height = (GLsizei) self.height;
GLint oldBind = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBind);
glBindTexture(GL_TEXTURE_2D, self.textureID);
GLuint fbo[1];
glGenFramebuffersOES(1, fbo);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbo[0]);
GLuint rbo[1];
glGenRenderbuffersOES(1, rbo);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, rbo[0]);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA4_OES, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, rbo[0]);
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(#"Incomplete FBO");
}
// draw
static float texCoords[8] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
static float vertexCoords[8] = { -1.0f, -1.0f, 1-.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f };
glMatrixMode (GL_PROJECTION);
glPushMatrix();
glLoadIdentity ();
glOrthof(0.0f, self.width, self.height, 0.0f, 0.0f, 1.0f);
glMatrixMode (GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glVertexPointer(2, GL_FLOAT, 0, vertexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// end draw
GLsizei count = width * height * 4;
GLubyte * pixels = (GLubyte *)malloc((sizeof(GLubyte) * count));
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glBindTexture(GL_TEXTURE_2D, oldBind);
glDeleteRenderbuffersOES(1, rbo);
glDeleteFramebuffersOES(1, fbo);
return [NSMutableData dataWithBytes:pixels length:count];
}
What am I doing wrong?
So, I was eventually able to solve this using a variation of the code seen here. My code is:
#interface SPRenderTexture (RenderToImage)
- (NSMutableData *)renderToPixelData;
#end
#implementation SPRenderTexture (RenderToImage)
- (NSMutableData *)renderToPixelData
{
__block NSMutableData * pixels = nil;
[self bundleDrawCalls:^()
{
float scale = [SPStage contentScaleFactor];
int width = scale * self.width;
int height = scale * self.height;
int nrOfColorComponents = 4; //RGBA
int rawImageDataLength = width * height * nrOfColorComponents;
GLenum pixelDataFormat = GL_RGBA;
GLenum pixelDataType = GL_UNSIGNED_BYTE;
GLubyte *rawImageDataBuffer = (GLubyte *) malloc(rawImageDataLength);
glReadPixels(0, 0, width, height, pixelDataFormat, pixelDataType, rawImageDataBuffer);
pixels = [[NSMutableData alloc] initWithBytes:rawImageDataBuffer length:rawImageDataLength];
}];
return [pixels autorelease];
}
#end
I hope this will be useful to other people.
Related
I'm trying to use OpenCL to draw to a cl_image that I got from a OpenGL texture and then render that texture. The problem is when I run my code on CL_DEVICE_TYPE_CPU it works fine however when I run on CL_DEVICE_TYPE_GPU the texture appears to be some random pixels. I'm new to OpenCL and not sure what's goin on so I'll post code below, also using OpenCL on OSX.
Host Code:
#import "GLView.h"
#import <GLKit/GLKit.h>
#import <OpenCL/OpenCL.h>
#import "kernel.cl.h"
#define WIDTH 500
#define HEIGHT 500
static GLfloat squareVertexData[] =
{
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f
};
#interface GLView ()
#property (strong, nonatomic) GLKBaseEffect *effect;
#property (nonatomic) GLuint vertexArray;
#property (nonatomic) GLuint vertexBuffer;
#property (nonatomic) GLuint tex;
#property (nonatomic) cl_image clImage;
#property (nonatomic) dispatch_queue_t queue;
#end
#implementation GLView
#pragma mark - Lifecycle methods
- (void)awakeFromNib
{
NSOpenGLPixelFormatAttribute attrs[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAOpenGLProfile,
NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize, 8,
NSOpenGLPFAAlphaSize, 8,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
[self setPixelFormat:pixelFormat];
NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
CGLEnable([context CGLContextObj], kCGLCECrashOnRemovedFunctions);
[self setOpenGLContext:context];
}
- (void)dealloc
{
[self.openGLContext makeCurrentContext];
glDeleteBuffers(1, &_vertexBuffer);
glDeleteVertexArrays(1, &_vertexArray);
glDeleteTextures(1, &_tex);
gcl_release_image(self.clImage);
}
#pragma mark - NSOpenGLView methods
- (void)prepareOpenGL
{
GLint swapInterval = 1;
[self.openGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
glGenVertexArrays(1, &_vertexArray);
glBindVertexArray(self.vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 20, (char *)NULL + (0));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 20, (char *)NULL + (12));
glBindVertexArray(0);
self.effect = [[GLKBaseEffect alloc] init];
self.effect.transform.projectionMatrix = GLKMatrix4MakeOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
glGenTextures(1, &_tex);
glBindTexture(GL_TEXTURE_2D, self.tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
self.effect.texture2d0.name = self.tex;
CGLShareGroupObj sharegroup = CGLGetShareGroup(self.openGLContext.CGLContextObj);
gcl_gl_set_sharegroup(sharegroup);
self.clImage = gcl_gl_create_image_from_texture(GL_TEXTURE_2D, 0, self.tex);
self.queue = gcl_create_dispatch_queue(CL_DEVICE_TYPE_GPU, NULL);
dispatch_sync(self.queue, ^{
cl_ndrange range = {
2,
{ 0 },
{ WIDTH, HEIGHT },
{ 0 }
};
mykernel_kernel(&range, self.clImage);
});
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(self.vertexArray);
[self.effect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
[self.openGLContext flushBuffer];
}
#end
Kernel Code:
kernel void mykernel(write_only image2d_t image)
{
size_t x = get_global_id(0);
size_t y = get_global_id(1);
uint4 color;
color.x = 255;
color.w = 255;
write_imageui(image, (int2) (x,y), color);
}
I’m not clear why you’re asking for:
NSOpenGLPFAColorSize, 8,
This seems like not a lot of color. Possibly it’d work better if you ask for 32-bits (8 per pixel, plus alpha at end?):
NSOpenGLPFAColorSize, 32,
That’s the default created by Scene Kit, anyhow.
I tried to display a picture, but it is not displayed.
Here is my code for an NSOpenGLView subclass:
//
// MyOpenGLView.m
// OpenGLTests
//
// Created by Tom Schamberger on 10.12.12.
// Copyright (c) 2012 Tom Schamberger. All rights reserved.
//
#import "MyOpenGLView.h"
#implementation MyOpenGLView
- (id)initWithFrame:(NSRect)frame
{
NSOpenGLPixelFormat * pf = [MyOpenGLView basicPixelFormat];
self = [super initWithFrame: frame pixelFormat: pf];
return self;
}
+ (NSOpenGLPixelFormat*) basicPixelFormat
{
NSOpenGLPixelFormatAttribute attributes [] = {
NSOpenGLPFAWindow,
NSOpenGLPFADoubleBuffer, // double buffered
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer
(NSOpenGLPixelFormatAttribute)nil
};
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
}
- (void) prepareOpenGL
{
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glPolygonOffset (1.0f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
if([self loadTextures])
NSLog(#"Load");
}
- (void)drawRect:(NSRect)dirtyRect
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture( GL_TEXTURE_2D, texture);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glColor3f(1, 1, 1);
glBegin( GL_QUADS );
glTexCoord2f( 0.0f, 0.0f);
glVertex2f( -0.5f, -0.5f);
glTexCoord2f( 1.0f, 0.0f);
glVertex2f( 0.5f, -0.5f);
glTexCoord2f( 1.0f, 1.0f);
glVertex2f( 0.5f, 0.5f);
glTexCoord2f( 0.0f, 1.0f);
glVertex2f( -0.5f, 0.5f);
glEnd();
glFlush();
}
- (BOOL) loadTextures
{
NSImage *img = [NSImage imageNamed:#"NeHe.bmp"];
if(img == nil)
return FALSE;
else if(img.size.height == 0 || img.size.width == 0)
return FALSE;
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithData: [img TIFFRepresentation]];
glGenTextures( 1, &texture);
glBindTexture( GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, rep.size.width,
rep.size.height, 0, GL_RGB,
GL_UNSIGNED_BYTE, rep.bitmapData);
return TRUE;
}
#end
It draws a rectangle, but the texture is not displayed.
You should probably set you clear color alpha to 0.0 rather than 0.5
This code for loading a texture works.
backGroundPath = #"Background.bmp";
NSData* backGroundData = [NSData dataWithContentsOfFile:backGroundPath options:NSUncachedRead error:nil];
backGroundImage = [NSBitmapImageRep imageRepWithData:backGroundData];
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures( 1, backGroundTexture);
glBindTexture(GL_TEXTURE_2D, backGroundTexture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backGroundImage.size.width,
backGroundImage.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
backGroundImage.bitmapData);
I need to draw small circles on a frame and make them to disappear after few frames (fading out). How can I achieve this with OpenGL ES?
This is what I have so far, the code to draw the circle in a frame:
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GLfloat vertices[720];
for (int i = 0; i < 720; i += 2) {
vertices[i] = (cos(DEGREES_TO_RADIANS(i)) * 1);
vertices[i+1] = (sin(DEGREES_TO_RADIANS(i)) * 1);
}
glVertexPointer(2, GL_FLOAT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
What I don't understand is how to keep track of the same circle and fade it in the successive frames.
Thanks
You will need to re-render all objects (circles) on every frame. So you need to keep around a data structure which holds the information about the circles (probably their center, radius, and opacity would be sufficient). Something like this:
typedef struct Circle {
NSPoint center;
float radius;
float opacity;
} Circle;
Circle allCircles [ kMaxNumCircles ];
Then, when you go to draw them, you iterate over the array of circles, updating their opacity and then drawing them:
for (int i = 0; i < kMaxNumCircles; i++)
{
allCircles [ i ].opacity -= someDelta;
drawCircle (allCircles [ i ]);
}
The drawCircle() function could just be what you've written above:
void drawCircle(Circle c)
{
GLfloat vertices[720];
for (int i = 0; i < 720; i += 2) {
vertices[i] = (cos(DEGREES_TO_RADIANS(i)) * 1) + c.center.x;
vertices[i+1] = (sin(DEGREES_TO_RADIANS(i)) * 1) + c.center.y;
}
glVertexPointer(2, GL_FLOAT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glColor4f(1.0f, 1.0f, 0.0f, c.opacity);
glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
}
I use a NSOpenGLView.
- (void)initGL
{
// Setup OpenGL states
[[self openGLContext] makeCurrentContext];
// Setup OpenGL states
glMatrixMode(GL_PROJECTION);
CGRect frame = self.bounds;
// Setup the view port in Pixels
glOrtho(0, frame.size.width, 0, frame.size.height, -1, 1);
glViewport(0, 0, frame.size.width, frame.size.height);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DITHER);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_BLEND);
//glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_POINT_SPRITE);
glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
self.pointSize = pointSizeForDrawing;
}
Framebuffer creation and binding.
- (BOOL)createFramebuffer
{
//Generating two buffers
glGenRenderbuffers( NumRenderbuffers, renderbuffer );
glBindRenderbuffer( GL_RENDERBUFFER, renderbuffer[Color]);
glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA, self.bounds.size.width, self.bounds.size.height);
glBindRenderbuffer( GL_RENDERBUFFER, renderbuffer[Depth] );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, self.bounds.size.width, self.bounds.size.height);
//Generating framebuffer
glGenFramebuffers( 1, &framebuffer );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, framebuffer );
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer[Color] );
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[Depth] );
glEnable( GL_DEPTH_TEST );
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
DLog(#"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
return NO;
}
return YES;
}
Line rendering
- (void)renderLineFromPoint:(CGPoint)start ToPoint:(CGPoint)end
{
GLsizei vertexCount = 0;
DLog(#"start: %# end %#", NSStringFromCGPoint(start), NSStringFromCGPoint(end));
// Add points to the buffer so there are drawing points every X pixels
int count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / brushPixelStep), 1);
for(int i = 0; i < count; ++i)
{
if(vertexCount == vertexMax)
{
vertexMax = 2 * vertexMax;
vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat));
}
vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);
vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);
vertexCount += 1;
}
// Render the vertex array
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, framebuffer);
glClear(GL_DEPTH_BUFFER_BIT);
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_POINTS, 0, vertexCount);
}
And finally display buffer
- (void)displayBuffer
{
DLog(#"Display");
glBindFramebuffer( GL_READ_FRAMEBUFFER, framebuffer );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glViewport(0, 0, self.bounds.size.width, self.bounds.size.height);
glBlitFramebuffer( 0, 0, self.bounds.size.width, self.bounds.size.height, 0, 0, self.bounds.size.width, self.bounds.size.height, GL_COLOR_BUFFER_BIT, GL_NEAREST );
glSwapAPPLE();
}
It does not matter if I change line glDrawArrays(GL_POINTS, 0, vertexCount); to glDrawArrays(GL_POINTS, 0, 1);. The effect is still the same despite value of vertexCount different than 1. Any ideas?
First possible problem:
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
As I understand vertexBuffer is an array of structures. So the error could be that the third parameter is 0 but it should be the size of this structure. For example:
CVertex3 v[3];
...
glVertexPointer(3,GL_FLOAT,sizeof(CVertex3),v);
Updated
Second possible problem:
try to remove glEnable(GL_DEPTH_TEST); it wouldn't work properly but I think I have seen the similar situation in Internet
I am a complete idiot at OpenGL, and I can't figure out why my code isn't working, only the clear color shows. I am trying to set up some simple rendering on iOS. Please can somebody help me?
My main scene code is:
//
// Scene.m
#import "Scene.h"
GLfloat vertices[] = {
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0
};
#implementation Scene
+(Class)layerClass {
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CAEAGLLayer *glLayer = (CAEAGLLayer *)self.layer;
glLayer.opaque = YES;
glLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!context) {
NSLog(#"Failed to create 2.0 context");
exit(1);
}
[EAGLContext setCurrentContext:context];
GLuint framebuffer, colorRenderbuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:glLayer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint program = [self loadShaders:#"Test.vp" frag:#"Test.fp"];
positionIndex = glGetAttribLocation(program, "position");
mvpIndex = glGetUniformLocation(program, "mvp");
glLinkProgram(program); //added this
GLint param;
glGetProgramiv(program, GL_LINK_STATUS, ¶m);
if (param == GL_FALSE) {
NSLog(#"Failed to link the program");
exit(1);
}
glUseProgram(program);
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(render:)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
return self;
}
-(void)render:(CADisplayLink *)_displayLink {
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(positionIndex);
glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid *)0);
GLfloat mvp[] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
glUniformMatrix4fv(mvpIndex, 1, GL_FALSE, mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[context presentRenderbuffer:GL_RENDERBUFFER];
glDisableVertexAttribArray(positionIndex);
}
-(GLuint)loadShaders:(NSString *)vertShader frag:(NSString *)fragShader {
NSString *vertPath = [[NSBundle mainBundle] pathForResource:[vertShader stringByDeletingPathExtension] ofType:#"vp"];
NSString *fragPath = [[NSBundle mainBundle] pathForResource:[fragShader stringByDeletingPathExtension] ofType:#"fp"];
if (!vertPath || !fragPath) {
NSLog(#"Failed to find paths of shaders");
exit(1);
}
NSError *error;
const GLchar* vertSource = [[NSString stringWithContentsOfFile:vertPath encoding:NSUTF8StringEncoding error:&error] UTF8String];
const GLchar* fragSource = [[NSString stringWithContentsOfFile:fragPath encoding:NSUTF8StringEncoding error:&error] UTF8String];
if (!vertSource || !fragSource) {
NSLog(#"Faild to load shader sources\n%#", [error localizedDescription]);
exit(1);
}
GLuint vert, frag;
vert = glCreateShader(GL_VERTEX_SHADER);
frag = glCreateShader(GL_FRAGMENT_SHADER);
GLint length = strlen(vertSource);
glShaderSource(vert, 1, &vertSource, &length);
length = strlen(fragSource);
glShaderSource(frag, 1, &fragSource, &length);
glCompileShader(vert);
glCompileShader(frag);
GLint success;
glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
if (success == GL_FALSE) {
GLchar messages[256];
glGetShaderInfoLog(vert, sizeof(messages), 0, &messages[0]);
NSLog(#"Failed to compile vertex shader\n%#", [NSString stringWithUTF8String:messages]);
exit(1);
}
glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
if (success == GL_FALSE) {
GLchar messages[256];
glGetShaderInfoLog(frag, sizeof(messages), 0, &messages[0]);
NSLog(#"Failed to compile fragment shader\n%#", [NSString stringWithUTF8String:messages]);
exit(1);
}
GLuint prog = glCreateProgram();
glAttachShader(prog, vert);
glAttachShader(prog, frag);
//Removed glLinkProgram()
return prog;
}
#end
The shader code is:
attribute vec2 position;
uniform mat4 mvp;
void main(void) {
gl_Position = mvp * vec4(position.xy, -1.0, 1.0);
}
and
void main() {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
Thank you in advance
glEnableVertexAttribArray(positionIndex);
glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, vertices);
This line is incorrect:
glDisableVertexAttribArray(positionIndex);
Don't disable it before you use it, or you'll lose it
Also, since you are using a vbo for your verts, you don't need to do this:
glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, vertices);
Simply switch it to this:
glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
You have a vbo bound to the GPU, it will use that buffer to draw. Use the glVertexAttribPointer to define the offset into the vbo it will find the first element for the given attribute.
#kibab The suggestion I made for the vbo is correct.
He was receiving EXC_BAD_ACCESS due to his attribute not binding to his shader. See comments below. As for the mvp you are incorrect, again. The mvp is meant to convert points into a coordinate system of -1.0, -1.0, to 1.0, 1.0. Meaning his vertices should be showing given their values.
See http://flylib.com/books/2/789/1/html/2/images/03fig02.jpg.
Also changing the z coordinate will do nothing for you. Change your vertice to start at -1.0,-1.0 and go to 1.0,1.0 a full screen box just so we can get something on screen.
Assuming you aren't using any apple provided gl classes your glViewPort isn't being set.
Try using your view's bound's size
glViewport(0, 0, bouds.width, bounds.height);
Also please put your verts on 0.0 z instead of -1.0
Also lets try this, just to figure out what's going wrong!
Try not using a vertex buffer object and passing it straight over like this.
Also don't worry about disabling your attribute at the moment, lets get something on screen first.
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f , 0.0f,
-1.0f, 1.0f , 0.0f,
1.0f, 1.0f , 0.0f,};
glVertexAttribPointer(positionIndex,3,GL_FLOAT,0,0,vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);