基于Apple的'glPaint'在白色背景上的OpenGL绘画程序 - 如何融合?

时间:2010-05-08 01:23:23

标签: iphone opengl-es paint blending

尝试为iPhone编写一个简单的绘图程序,我正在使用Apple的glPaint示例作为指南。唯一的问题是,绘画不适用于白色背景,因为白色+颜色=白色。我尝试过不同的混合功能,但是无法使用正确的设置和/或画笔组合来实现这一功能。我看过关于这个问题的类似帖子,但没有答案。有谁知道这可能有用吗?

修改
我甚至没有真正的透明效果,在这一点上,如果我能画出圆形末端的实线,我会很高兴。

7 个答案:

答案 0 :(得分:3)

我有白色背景工作(使用默认的GLPaint代码),只需更改擦除方法中的清晰颜色,即

- (void) erase
{
    [EAGLContext setCurrentContext:context];

    // Clear the buffer
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    //glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearColor(1.0, 1.0, 1.0, 0.0); // Change to white
    glClear(GL_COLOR_BUFFER_BIT);

    // Display the buffer
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

默认的混合功能和画笔图像似乎正常工作。

答案 1 :(得分:2)

您可以减去其相反的颜色,而不是将颜色添加到混合物中吗?这大致是油漆和灯光在现实生活中的作用,应该给出正确的功能。

例如:如果用户正在Red:255 Green:0 Blue:100 Opacity:0.5中绘画,则应对像素执行此操作:

pixel.red -= (255-paint.red) * paint.opacity;      //Subtract 0
pixel.green -= (255-paint.green) * paint.opacity;  //Subtract 127.5
pixel.blue -= (255-paint.blue) * paint.opacity;    //Subtract 77.5

编辑:正如你所指出的那样,它不是预期的,因为用全红色绘制的全蓝色会变成黑色,因为它们会相互减去。

可能的解决方法是结合加法和减法方法。

例如,如果您添加0.5*paint.colour并减去0.5*paint.complementaryColour,则将全红色添加为全蓝会导致:

newPixel.red -> 0 +  127.5 -  0  = 127.5
newPixel.green -> 0 + 0 - 127.5  = 0     //Cap it off, or invent new math =D
newPixel.blue -> 255 + 0 - 127.5 = 127.5

正如您所看到的,这会产生漂亮的紫色,这是蓝色和红色的组合。您可以调整加法到减法逻辑的比例,以模拟油漆混合的程度。

希望有所帮助! =)

答案 2 :(得分:2)

是的,我有同样的问题。刷子的边缘比它们应该更暗。事实证明,apple的api pre将alpha加倍到rgb通道。

所以我反驳说,在photoshop中使用rgb值并且没有alpha通道制作灰度画笔。这应该看起来像你希望你的画笔用白色代表全彩色颜料,黑色代表没有颜色色素沉着。 我按照它在apple的glPaint示例代码中的方式加载该画笔。然后,我将R通道(或G或B通道,因为它们都相等)复制到纹理的alpha通道中。接下来,我将刷子纹理的所有像素的R-G-B值设置为最大值。

所以现在你的画笔有一个alpha通道,其中包含画笔外观的数据。并且RGB都是1。

最后我使用了混合功能:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

并且不要忘记在画画之前设置颜色。

glColor4f(1.0f,0.0f,0.0f,1.0f); //red color

查看下面的代码,看看它是否适合您:

-(GLuint) createBrushWithImage: (NSString*)brushName
{

    GLuint            brushTexture;
    CGImageRef      brushImage;
CGContextRef    brushContext;
GLubyte         *brushData,*brushData1;
size_t          width, height;

//initialize brush image
brushImage = [UIImage imageNamed:brushName].CGImage;

// Get the width and height of the image
width = CGImageGetWidth(brushImage);
height = CGImageGetHeight(brushImage);

//make the brush texture and context
if(brushImage) {
    // Allocate  memory needed for the bitmap context
    brushData = (GLubyte *) calloc(width * height *4, sizeof(GLubyte));
    // We are going to use brushData1 to make the final texture
    brushData1 = (GLubyte *) calloc(width * height *4, sizeof(GLubyte));
    // Use  the bitmatp creation function provided by the Core Graphics framework. 

    brushContext = CGBitmapContextCreate(brushData, width, height, 8, width *4 , CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
    // After you create the context, you can draw the  image to the context.
    CGContextDrawImage(brushContext, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), brushImage);
    // You don't need the context at this point, so you need to release it to avoid memory leaks.
    CGContextRelease(brushContext);

    for(int i=0; i< width*height;i++){
                    //set the R-G-B channel to maximum
        brushData1[i*4] = brushData1[i*4+1] =brushData1[i*4+2] =0xff;
                    //store originally loaded brush image in alpha channel
        brushData1[i*4+3] = brushData[i*4];
    }

    // Use OpenGL ES to generate a name for the texture.
    glGenTextures(1, &brushTexture);
    // Bind the texture name. 
    glBindTexture(GL_TEXTURE_2D, brushTexture);
    // Set the texture parameters to use a minifying filter and a linear filer (weighted average)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    // Specify a 2D texture image, providing the a pointer to the image data in memory
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData1);
    // Release  the image data; it's no longer needed
    free(brushData1);
    free(brushData);
}

return brushTexture; }

答案 3 :(得分:1)

我遇到了类似的事情。以下混合函数调用解决了它,没有任何复杂的数学运算。

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

在你的glDraw调用之前添加它,你应该可以使用任何纹理作为画笔进行绘制。

答案 4 :(得分:0)

实际上这效果更好:

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

答案 5 :(得分:0)

示例代码GLPaint在函数glBlendFunc(GL_SRC_ALPHA, GL_ONE)中使用glBlendFunc(GL_SRC_ALPHA, GL_ONE)- (id)initWithCoder:(NSCoder*)coder模式。因此,当颜色为白色时,将看不到所有其他颜色。 我也想解决它。

答案 6 :(得分:0)

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

这是最佳答案。你必须为画笔图片充电。图片必须是alpha背景和椭圆形。