Finding Exact Screen Dimensions - ios

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

Related

failed to bind EAGLDrawable in CADisplayLink render loop

i use CADisplayLink render-loop callback to render a serial of image textures with openGLes.
after CADisplayLink's first callback called, i just get these error output
Failed to bind EAGLDrawable: <CAEAGLLayer: 0x946bb40> to GL_RENDERBUFFER 2
Failed to make complete framebuffer object 8cd6
i setup the renderBuffer&frameBuffer and call glFramebufferRenderbuffer in controller's viewDidLoad stage, the return of glCheckFramebufferStatus is fine in that stage.
this is the code I'm using.
//GLKViewController.m
typedef struct {
GLKVector3 positionCoords;
GLKVector2 textureCoords;
}SceneVertex;
static const SceneVertex vertices[] =
{
{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}}, // lower left corner
{{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f}}, // lower right corner
{{-1.0f, 1.0f, 0.0f}, {0.0f, 1.0f}}, // upper left corner
{{ 1.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
};
#interface myViewController () //glkViewController
#property (nonatomic) GLuint renderBuffer;
#property (nonatomic) GLuint frameBuffer;
#property (nonatomic) GLuint glBuffer;
#property (nonatomic) int renderWidth;
#property (nonatomic) int renderHeight;
#property(strong, nonatomic) CADisplayLink* displayLink;
#property(strong, nonatomic) EAGLContext* context;
#end
#implementation myViewController
-(void)setupBuffers
{
glGenFramebuffers(1, &_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glGenRenderbuffers(1, &_renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
[self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.view.layer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, _renderBuffer);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_renderWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_renderHeight);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
NSLog(#"AAfailed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
glGenBuffers(1,&_glBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _glBuffer);
glBufferData(
GL_ARRAY_BUFFER, // Initialize buffer contents
sizeof(vertices), // Number of bytes to copy
vertices, // Address of bytes to copy
GL_STATIC_DRAW); // Hint: cache in GPU memory
}
-(void)loadView
{
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
self.view = [[myView alloc] initWithFrame:[[UIScreen mainScreen] bounds] context:_context];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[EAGLContext setCurrentContext:self.context];
[self setupBuffers];
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(render)];
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
_displayLink.frameInterval = 1;
}
- (void)render
{
myView *view = (myView*)self.view;
NSData *image = [view getOneImage]; //if nil, return or sleep&reget;
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, _renderWidth, _renderHeight);
GLuint texture = -1;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexImage2D(
GL_TEXTURE_2D, 0, /* target, level */
GL_RGB, /* internal format */
_renderWidth, _renderHeight, 0, /* width, height, border */
GL_RGB, GL_UNSIGNED_BYTE, /* external format, type */
image.bytes /* pixels */
);
glBindBuffer(GL_ARRAY_BUFFER,_glBuffer);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, // Identifies the attribute to use
3, // number of coordinates for attribute
GL_FLOAT, // data is floating point
GL_FALSE, // no fixed point scaling
sizeof(SceneVertex), // total num bytes stored
NULL+offsetof(SceneVertex, positionCoords));
glBindBuffer(GL_ARRAY_BUFFER, _glBuffer);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, // Identifies the attribute to use
2, // number of coordinates for attribute
GL_FLOAT, // data is floating point
GL_FALSE, // no fixed point scaling
sizeof(SceneVertex), // total num bytes stored per vertex
NULL+offsetof(SceneVertex, textureCoords));
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawArrays(GL_TRIANGLES, 1, 4);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
[_context presentRenderbuffer:GL_RENDERBUFFER];
glFlush();
glDeleteTextures(1, &texture);
}
#end
//GLKView
#implementation myView
+ (Class)layerClass {
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame context:(EAGLContext *)context
{
self = [super initWithFrame:frame];
if (self) {
self.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
self.context = context;
CAEAGLLayer *layer= (CAEAGLLayer *)self.layer;
self.images = [[NSMutableArray alloc] init];
layer.opaque = YES;
layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
}
return self;
}
#end
//APPDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[QCPViewController alloc]init];
[self.window makeKeyAndVisible];
return YES;
}
This occurs when you try to draw an openGL view that isn't currently on screen. In my case, the view wasn't installed in the current size class in my storyboard.
If you are using storyboards, double check that the view is installed in the current size class
Select the open GL view in the storyboard
Go to the Attributes inspector
Verify the view is installed in all size classes like below
I'm experiencing the same thing. I'm creating and adding the SCNView on a callback from CADisplayLink. It is very laggy, it is not visible and the error shows up in console. When I just say dispatch_async(dispatch_get_main_queue(), ^{ /* code */ }); Then everything is fine.

iOS OpenGLES strange behavior when rendering multiple objects

I am trying to render two cubes with textures ("body" and "head"). There is a single texture atlas which has all cube faces. To achieve this, I have created a class to encapsulate all the code which draws a cube: MSTexturedCube.
// In MSTexturedCube.h
#import <Foundation/Foundation.h>
#import <GLKit/GLKit.h>
#interface MSTexturedCube : NSObject {
GLKVector3 _vertices[8];
GLKVector3 _triangleVertices[36];
GLKVector2 _textureVertices[36];
}
#property (nonatomic, assign) float xRotationAngle;
#property (nonatomic, assign) float yRotationAngle;
#property (nonatomic, assign) GLKVector3 scale; // x, y, z scale
#property (nonatomic, assign) GLKVector3 translation; // x, y, z translation
- (id)initWithTexture:(GLKTextureInfo *)textureInfo vertexData:(GLKVector2[36])textureVertexData;
- (id)initWithTexture:(GLKTextureInfo *)textureInfo frontFaceCoords:(GLKVector2[4])front right:(GLKVector2[4])right back:(GLKVector2[4])back left:(GLKVector2[4])left top:(GLKVector2[4])top bottom:(GLKVector2[4])bottom;
- (void)draw;
- (void)setVertices:(GLKVector3[8])verticesArray;
#end
// In MSTexturedCube.m
#import "MSTexturedCube.h"
static int vertexIndices[36] = {
// Front
0, 1, 2,
0, 2, 3,
// Right
1, 5, 6,
1, 6, 2,
// Back
5, 4, 7,
5, 7, 6,
// Left
4, 0, 3,
4, 3, 7,
// Top
3, 2, 6,
3, 6, 7,
// Bottom
4, 5, 1,
4, 1, 0,
};
#interface MSTexturedCube ()
#property (nonatomic, strong) GLKBaseEffect *effect;
#property (nonatomic, strong) GLKTextureInfo *textureInfo;
- (void)setupOpenGL;
#end
#implementation MSTexturedCube
#synthesize effect = _effect;
#synthesize textureInfo = _textureInfo;
#synthesize xRotationAngle = _xRotationAngle;
#synthesize yRotationAngle = _yRotationAngle;
#synthesize scale = _scale;
#synthesize translation = _translation;
// Init methods
...
- (void)draw {
// Create matrices
GLKMatrix4 yRotation = GLKMatrix4MakeYRotation(self.yRotationAngle);
GLKMatrix4 xRotation = GLKMatrix4MakeXRotation(self.xRotationAngle);
GLKMatrix4 scale = GLKMatrix4MakeScale(self.scale.x, self.scale.y, self.scale.z);
GLKMatrix4 translation = GLKMatrix4MakeTranslation(self.translation.x, self.translation.y, self.translation.z);
GLKMatrix4 modelMatrix = GLKMatrix4Multiply(translation, GLKMatrix4Multiply(xRotation, GLKMatrix4Multiply(yRotation, scale)));
GLKMatrix4 viewMatrix = GLKMatrix4MakeLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
self.effect.transform.modelviewMatrix = GLKMatrix4Multiply(viewMatrix, modelMatrix);
self.effect.transform.projectionMatrix = GLKMatrix4MakePerspective(0.25 * M_PI, 1.0, 2.0, 500.0);
// Set texture properties if a texture is set
if (self.textureInfo) {
self.effect.texture2d0.envMode = GLKTextureEnvModeReplace;
self.effect.texture2d0.target = GLKTextureTarget2D;
self.effect.texture2d0.name = self.textureInfo.name;
}
// Prepare the effect to draw after creating matrices
[self.effect prepareToDraw];
// Set texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(self.textureInfo.target, self.textureInfo.name);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
// Set vertices
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, _triangleVertices);
// Set texture (if set)
if (self.textureInfo) {
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, _textureVertices);
}
// Draw
glDrawArrays(GL_TRIANGLES, 0, 36);
// Disable arrays
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
}
// Getters & setters
...
#pragma mark - Private methods
- (void)setupOpenGL {
// Set vertices array
_vertices[0] = GLKVector3Make(-0.5, -0.5, 0.5); // Left bottom front
_vertices[1] = GLKVector3Make( 0.5, -0.5, 0.5); // Right bottom front
_vertices[2] = GLKVector3Make( 0.5, 0.5, 0.5); // Right top front
_vertices[3] = GLKVector3Make(-0.5, 0.5, 0.5); // Left top front
_vertices[4] = GLKVector3Make(-0.5, -0.5, -0.5); // Left bottom back
_vertices[5] = GLKVector3Make( 0.5, -0.5, -0.5); // Right bottom back
_vertices[6] = GLKVector3Make( 0.5, 0.5, -0.5); // Right top back
_vertices[7] = GLKVector3Make(-0.5, 0.5, -0.5); // Left top back
// Set the triangle vertices
for (int i = 0; i < 36; i++) {
_triangleVertices[i] = _vertices[vertexIndices[i]];
}
self.effect = [[GLKBaseEffect alloc] init];
}
In my GLKViewController subclass, which implements the GLKViewDelegate and the GLKViewControllerDelegate, I create two MSTexturedCube objects which I initialize with the necessary vertex data and texture vertex data. In the GLKViewDelegate I wrote this function:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
// Set background color
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
// Set properties
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
[self.cubes makeObjectsPerformSelector:#selector(draw)];
}
It works perfectly but for one problem: when I rotate the view, the second object in the cubes array renders without any problem, but the first object, even if it's nearer to the camera, appears absolutely transparent if it has the other object below. If it has only the background below it renders also opaque. ¿How can I fix this problem, and make objects respect the z-order?
I solved my problem.
I forgot to add to my EAGLContext a depth buffer by setting my GLView's drawableDepthFormat property to GLKViewDrawableDepthFormat16.
Although it doesn't appear in the question, I had tried to add the following two lines in the GLView's delegate method, but they did nothing:
glDepthFunc(GL_LEQUAL);
glClear(GL_DEPTH_BUFFER_BIT);
Obviously, because the buffer was not set. When I set GLKViewDrawableDepthFormat16 and I add this two lines it works perfectly.

IOS: OpenGL Triangle Not Showing up

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.

OpenGL ES 2.0 GLKit Draw a line

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.

Drawing a simple linear gradient inside a rect that is inside a view

I'm reading the documentation about gradients and I'm a little bit lost.
I have a view, and inside that view, I just want to draw a simple black to gray linear gradient inside a rect (smaller than the view), from bottom to top.
How may I do that without subclassing anything (I've read many things that need to subclass the view)?
I'm searching a way to do this as simple as I've ever done on various platforms. Something like (language free :-) ) :
blackcolor = MakeBlack();
whiteColor = MakeWhite();
startPoint = MakeStartPoint();
endPoint = MakeEndPoint();
onthisgraphicport = SetGraphicPort(self.view);
clippingRect = MakeClipRect();
DrawGradient(from:whiteColor, to:blackcolor, from:startPoint, to:endPoint, onthisgraphicport, intoThisRect:clippingRect);
Thank you for your help.
This code snippet might help. I found the code some time ago on the web. Unfortunately, I forgot the site, so not sure whom to give credit.
The code as is draws a white to black gradient. Just change the rect and the colors to your needs.
#interface MyView : UIView {
CGGradientRef _gradientRef;
}
#end
#implementation MyView
- (void) dealloc
{
[super dealloc];
}
- (id) initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
CGFloat colors[] =
{
1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
_gradientRef = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors) / (sizeof(colors[0]) * 4));
CGColorSpaceRelease(rgb);
}
return self;
}
- (void) drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGPoint start = rect.origin;
start.y = 0;
CGPoint end = CGPointMake(rect.origin.x, rect.size.height);
CGContextDrawLinearGradient(context, _gradientRef, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
[super drawRect:rect];
}
#end

Resources