问题
I have the same requirement as this question
I am right now at situation where i set UIImage on my opengl view. Below is the complete code i used to set uiimage. Also it includes the drawing code. Using below code I am able to set image and drawing on it.
when i do not set image in background it allows me to draw blur and smooth drawing
but if i set background image it draws solid drawing
I want smooth drawing on background image.
I have used some of GLPaint code of apple for drawing.
- (id)initWithCoder:(NSCoder*)coder
{
CGImageRef brushImage;
CGContextRef brushContext;
GLubyte *brushData;
size_t width, height;
if ((self = [super initWithCoder:coder]))
{
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = NO;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
nil];
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!_context || ![EAGLContext setCurrentContext:_context])
{
return nil;
}
{
brushImage = [UIImage imageNamed:@"Brush.png"].CGImage;
width = CGImageGetWidth(brushImage);
height = CGImageGetHeight(brushImage);
if(brushImage) {
brushData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
brushContext = CGBitmapContextCreate(brushData, width, width, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), brushImage);
CGContextRelease(brushContext);
glGenTextures(1, &brushTexture);
glBindTexture(GL_TEXTURE_2D, brushTexture);
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, brushData);
free(brushData);
}
}
// Setup OpenGL states
glMatrixMode(GL_PROJECTION);
CGRect frame = self.bounds;
glOrthof(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);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SPRITE_OES);
glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
glPointSize(10);
}
return self;
}
- (void)layoutSubviews
{
[EAGLContext setCurrentContext:_context];
[self destroyFramebuffer];
[self createFramebuffer];
if (texture) {
[self _updateContent];
glDeleteTextures(1, &texture);
texture = 0;
}
}
- (void)_updateContent {
NSUInteger width = self.frame.size.width;
NSUInteger height = self.frame.size.height;
CGFloat texWidth = (1.0 * width)/TEX_SIZE;
CGFloat texHeight = (1.0 * height)/TEX_SIZE;
GLfloat verts[12] = {
0, height,
width, height,
width, 0,
0, height,
0, 0,
width, 0
};
GLfloat txcoord[12] = {
0, texHeight,
texWidth, texHeight,
texWidth, 0,
0, texHeight,
0, 0,
texWidth, 0
};
[EAGLContext setCurrentContext:_context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer);
glVertexPointer(2, GL_FLOAT, 0, verts);
glTexCoordPointer(2, GL_FLOAT, 0, txcoord);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
[_context presentRenderbuffer:GL_RENDERBUFFER_OES];
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
- (void)setContent:(UIImage*)image
{
if (image) {
// self.isNotEmpty = YES;
CGImageRef contentImage = image.CGImage;
[EAGLContext setCurrentContext:_context];
CGFloat w = CGImageGetWidth(contentImage);
CGFloat h = CGImageGetHeight(contentImage);
GLubyte *data = (GLubyte *)calloc(TEX_SIZE * TEX_SIZE * 4, sizeof(GLubyte));
CGContextRef ctx = CGBitmapContextCreate(data, TEX_SIZE, TEX_SIZE, 8, TEX_SIZE * 4, CGImageGetColorSpace(contentImage), kCGImageAlphaPremultipliedLast);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -TEX_SIZE);
CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), contentImage);
CGContextRelease(ctx);
if (!texture) {
glGenTextures(1, &texture);
}
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
free(data);
}
[self setNeedsLayout];
glDisable(GL_VERTEX_ARRAY);
}
//Called on touchedMoved
- (void) renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end
{
glEnable(GL_BLEND);
if(1){
sharedDelegate = [AppDelegate appDelegate];
static GLfloat* vertexBuffer = NULL;
static NSUInteger vertexMax = 64;
NSUInteger vertexCount = 0,
count,
i;
GLenum err;
glColor4f(1.0, 0.0, 1.0, 1.0);
// Convert locations from Points to Pixels
CGFloat scale = self.contentScaleFactor;
start.x *= scale;
start.y *= scale;
end.x *= scale;
end.y *= scale;
// Allocate vertex array buffer
if(vertexBuffer == NULL)
vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat));
// Add points to the buffer so there are drawing points every X pixels
count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / kBrushPixelStep), 1);
for(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;
}
if(sharedDelegate.boolIsEraser)
{
glColor4f(1.0, 1.0, 1.0, 0.5);
glBlendFunc( GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
}
// Render the vertex array
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_POINTS, 0, vertexCount);
if(sharedDelegate.boolIsEraser){
// at last restore the mixed-mode
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
[_context presentRenderbuffer:GL_RENDERBUFFER_OES];
err = glGetError();
if (err != GL_NO_ERROR)
NSLog(@"Error in frame. glError: 0x%04X", err);
}
}
Any workaround to accomplish this? I am almost there to my goal but badly stuck here.Any help will be appreciated.
回答1:
You might try setting the shadow color to the same as the stroke color, and the stroke blur radius to however many points out from the edge of the stroke you want the blur to extend. You'll probably want to set the shadow offset to CGSizeZero
.
回答2:
You can try openGL code from This Link
or try this
CGSize offset;
float blur;//set this variable as per your requirement
offset.width = 10;
offset.height = -10;
CGContextSetShadow(context, offset, blur);
回答3:
I got the solution...
The thing remaining was I need to set my opengl states after i draw UIImage in opengl view. The same thing i did when i initialized brush texture...
I just added below code in LayoutSubviews
method after _updateContent
method
// Setup OpenGL states
glMatrixMode(GL_PROJECTION);
CGRect frame = self.bounds;
glOrthof(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);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SPRITE_OES);
glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE)
and now this code is working perfectly..
回答4:
You can use CGContextSetBlendMode(context, kCGBlendModeClear) ike real eraser effect
来源:https://stackoverflow.com/questions/15131213/drawing-with-with-blur-effect-on-image-using-opengl