I am trying to draw a line with OpenGL ES 2.0 GLKit. When I run the following code and use OpenGL ES Analyzer I get the following errors:
"Use of Non-Existent Program"
glDrawArrays(GL_LINE_STRIP,0,4)
"GL Error: Invalid Operation"
GL_INVALID_OPERATION <- glVertexPointer(2,GL_FLOAT,0,NULL)
GL_INVALID_OPERATION <- glEnableClientState(GL_VERTEX_ARRAY)
Here's my code:
#import "GLDrawingView.h"
const float data[] = {0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -0.0f, 0.0f, 1.0f};
#interface GLDrawingView () {
GLuint lineVBO;
}
#end
#implementation GLDrawingView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[EAGLContext setCurrentContext:self.context];
glGenBuffers(1, &lineVBO);
glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
}
return self;
}
- (void)drawRect:(CGRect)rect
{
glVertexPointer(2, GL_FLOAT, 0, NULL);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_LINE_STRIP, 0, sizeof(data) / sizeof(float) / 2);
}
#end
When you draw something in OpenGL ES 2.0 you must use shader program (glUseProgram) for rendering. You can not render without shaders in GLES2.
Related
I'm trying to draw multiple 2D objects and being able to move them with touch in OpenGL ES for iOS. I started a tutorial on drawing a square, but I have no idea how to add touch to move it. I'd like to be able to load multiple objects and move each of them around the screen with touch.
#import "HelloGLKitViewController.h"
typedef struct {
float Position[3];
float Color[4];
} Vertex;
const Vertex Vertices[] = {
{{1, -1, 0}, {1, 0, 0, 1}},
{{1, 1, 0}, {0, 1, 0, 1}},
{{-1, 1, 0}, {0, 0, 1, 1}},
{{-1, -1, 0}, {0, 0, 0, 1}}
};
const GLubyte Indices[] = {
0, 1, 2,
2, 3, 0
};
GLuint _vertexBuffer;
GLuint _indexBuffer;
#interface HelloGLKitViewController ()
#property (strong, nonatomic) EAGLContext *context;
#property (strong, nonatomic) GLKBaseEffect *effect;
#end
#implementation HelloGLKitViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!self.context) {
NSLog(#"Failed to create ES context");
}
GLKView *view = (GLKView *)self.view;
view.context = self.context;
[self setupGL];
}
- (void)viewDidUnload
{
[super viewDidUnload];
if ([EAGLContext currentContext] == self.context) {
[EAGLContext setCurrentContext:nil];
}
self.context = nil;
[self tearDownGL];
}
#pragma mark - GLKViewDelegate
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
[self.effect prepareToDraw];
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Position));
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Color));
glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
}
#pragma mark - GLKViewControllerDelegate
- (void)update {
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 4.0f, 10.0f);
self.effect.transform.projectionMatrix = projectionMatrix;
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -6.0f);
self.effect.transform.modelviewMatrix = modelViewMatrix;
}
- (void)setupGL {
[EAGLContext setCurrentContext:self.context];
self.effect = [[GLKBaseEffect alloc] init];
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}
- (void)tearDownGL {
[EAGLContext setCurrentContext:self.context];
glDeleteBuffers(1, &_vertexBuffer);
glDeleteBuffers(1, &_indexBuffer);
self.effect = nil;
}
#end
For the code you've posted, you would want to make another GLKBaseEffect, and update the modelviewMatrix properties of each matrix independently based on the touches you received.
I'm drawing a few lines using OpenGL ES and I need to change their thickness from 1 pixel to 3 pixels smoothly, but glLineWidth doesn't allow to set line thickness between 1.0 and 2.0.
Is it possible?
Here is my code
- (void)setupGL
{
[EAGLContext setCurrentContext:self.context];
self.effect = [[GLKBaseEffect alloc] init];
glEnable(GL_DEPTH_TEST);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(thinLines), thinLines, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindVertexArrayOES(0);
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray);
self.effect.constantColor = GLKVector4Make(lineR, lineG, lineB, 1.0f);
[self.effect prepareToDraw];
glLineWidth(1 + scaleQ);
glDrawArrays(GL_LINES, 0, thinLinesCount*2);
}
OpenGL ES (including 3.0) does not support antialiased lines. From documentation to glLineWidth:
The actual width is determined by rounding the supplied width to the
nearest integer.
So unfortunately you can't "smoothly" change line thickness.
I am trying and failing to draw a line with color using glkit / OpenGL Es2. I can draw the line, but it comes out as black.
My current approach is attempting to use a VBO containing both positional and color data.
Set-up:
typedef struct {
float Position[2];
float Color[4];
} LinePoint;
LinePoint line[] =
{
{{0.0, 0.0},{1.0,0.0,0.0,1}},
{{2.0, 3.0},{1.0,0.0,0.0,1}}
};
glGenBuffers(1, &_lineBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _lineBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(LinePoint)*2,line,GL_STATIC_DRAW);
In my drawInRect method:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
[EAGLContext setCurrentContext:self.context];
[self.effect prepareToDraw];
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindBuffer(GL_ARRAY_BUFFER, _lineBuffer);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition,2,GL_FLOAT,GL_FALSE,sizeof(LinePoint),(const GLvoid *) offsetof(LinePoint, Position));
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor,4,GL_FLOAT,GL_FALSE,sizeof(LinePoint),(const GLvoid *) offsetof(LinePoint, Color));
// Set the line width
glLineWidth(50.0);
// Render the line
glDrawArrays(GL_LINE_STRIP, 0, 2);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
}
Totally new to iOS OpenGL ES 2.0. I'm trying to precisely identify the boundaries of my screen (iPad) by drawing a simple rectangle. From what I have found, it looks to me like the dimensions of an iPad screen are 768 x 1024. However, my screen is not being covered correctly (note that I am drawing in landscape mode if that matters).
I'm not sure of the interaction between the vertices and how I'm using the projection matrix command.
'self.baseEffect.transform.projectionMatrix = GLKMatrix4MakeOrtho(0, FRAME_WIDTH*2, 0, FRAME_HEIGHT*2, 0, 0);'
If I delete this line, my rectangle renders with the lower left at the origin. But if I leave it in, it seems to render from the lower left, but the dimensions are too large and I can't seem to figure out how to change them predictably.
As you can see, I'm very confused. What is the best way of getting the exact screen dimensions. I need this to properly place other objects on the screen. Thanks!
#import "ViewController.h"
typedef struct {
GLKVector3 positionCoordinates;
GLKVector2 textureCoordinates;
} VertexData;
#define FRAME_HEIGHT 768.0f
#define FRAME_WIDTH 1024.0f
VertexData vertices[] = {
{ { 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f} }, // bottom left
{ {FRAME_WIDTH, 0.0f, 0.0f}, {1.0f, 0.0f} }, // bottom right
{ { 0.0f, FRAME_HEIGHT, 0.0f}, {0.0f, 1.0f} }, // top left
{ { 0.0f, FRAME_HEIGHT, 0.0f}, {0.0f, 1.0f} }, // top left
{ {FRAME_WIDTH, 0.0f, 0.0f}, {1.0f, 0.0f} }, // bottom right
{ {FRAME_WIDTH, FRAME_HEIGHT, 0.0f}, {1.0f, 1.0f} } // top right
};
#interface ViewController ()
#property (nonatomic, strong) EAGLContext *context;
#property (nonatomic, strong) GLKBaseEffect *baseEffect;
#end
#implementation ViewController {
GLuint _vertexBufferID;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
GLKView *view = (GLKView *) self.view;
view.context = self.context;
[EAGLContext setCurrentContext:self.context];
self.baseEffect = [[GLKBaseEffect alloc] init];
self.baseEffect.useConstantColor = YES;
self.baseEffect.constantColor = GLKVector4Make(1.0f, 0.0f, 0.0f, 1.0f);
self.baseEffect.transform.projectionMatrix = GLKMatrix4MakeOrtho(0, FRAME_WIDTH*2, 0, FRAME_HEIGHT*2, 0, 0);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glGenBuffers(1, &_vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), offsetof(VertexData, positionCoordinates));
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - GKLView delegate methods
- (void) glkView: (GLKView *) view drawInRect:(CGRect)rect{
glClear(GL_COLOR_BUFFER_BIT);
[self.baseEffect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 6);
}
- (void) update {
}
#end
You should use FRAME_HEIGHT and FRAME_WIDTH, not twice them.
You can obtain the screen dimensions with:
CGSize screenSize = [UIScreen mainScreen].bounds.size;
however, be wary of using this during application start-up.
To get the orientation of the current view controller:
[UIViewController interfaceOrientation]
To obtain the device orientation:
[[UIDevice currentDevice] orientation]
... or ...
[[UIApplication sharedApplication] statusBarOrientation];
In your case, you can simply use the bounds of EAGLView that you have:
CGSize viewSize = self.view.bounds.size
I have a GLKViewController that has an implementation as follows...
#import "game-gl.h"
....
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
renderFrameLine();
}
game-gl.c ( I started with s = .5)
void renderFrameLine() {
printf("Inside Render Line \n");
if(f>1.0f){
f = 0.0f;
}
else{
f = f+.01;
}
glClearColor(f, 0.65f, f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(s >2.0f){
s = -2.0f;
}
else{
s = s + 0.10f;
}
GLfloat vVertices[] = { s, s, 0.0f, s, -s, 0.0f, -s, s,
0.0f};
GLfloat colors[] = {
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f};
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 4);
}
When I run the app the background changes color but the Triangle never shows up. Any idea what I am doing wrong?
Problem appears to be with shaders not compiling...
shader = glCreateShader(type);
if (shader == 0){
#ifdef __APPLE__
printf("Shader Failed %d\n", type);
#endif
return 0;
}
Prints out that the shader failed (type = GL_VERTEX_SHADER)
I commented this out and I still get the same response, only everything else seems to compile ok...
UPDATE
I also see the following warning, I don't think it is related since the compile check passes but....
/Users/me/Development/test3/test3/game-gl.c:97:46: Passing 'GLbyte [148]' to parameter of type 'const char *' converts between pointers to integer types with different sign
But as I said this check seems to pass...
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
UPDATE AGAIN
Ok now we are getting some where...
programObject = glCreateProgram();
if(programObject == 0){
printf("Invalid program returned \n");
}
Prints off that the program is invalid ?!?!?!?
And Again
So I changed to try and grab the program in the .m file but it is still 0.
if(_program == 0){
NSLog(#"Still can not create program");
}
else{
resizeViewport(screenWidth, screenHeight);
InitializeOpenGL(0, 0, _program);
}
Where is your shader code? Are you creating a fragment shader? Creating a program? Linking? if thats not compiling, then thats your first problem. But you can get useful error messages from gl that will help you there.
Besides that, you should enable the attribute pointer before assigning the data.
Also, make sure you're not culling clockwise faces (CCW instead)... If u have face culling enabled that is.
For the GLKViewController you apparently have to set the context before getting the program. Adding this line...
[EAGLContext setCurrentContext:self.context];
before initializing the GL made it work.