2

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

编辑:
我什至没有真正的透明效果,在这一点上,如果我能画出圆角的实线,我会很高兴。

4

7 回答 7

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];
}

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

于 2011-01-12T16:53:58.997 回答
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

如您所见,这会产生漂亮的紫色,它是蓝色和红色的组合。您可以调整添加剂与减法逻辑的比例,以模拟油漆的混合效果。

希望有帮助!=)

于 2010-05-08T03:08:42.730 回答
2

是的,我有同样的问题。刷子的边缘比它们应该的要暗。事实证明,苹果的 api pre 将 alpha 乘以 rgb 通道。

所以我通过在 Photoshop 中制作一个只有 rgb 值且没有 alpha 通道的灰度画笔来反驳这一点。这应该看起来像您希望画笔的方式,白色代表全彩色色素沉着,黑色代表无色素沉着。我按照苹果的 glPaint 示例代码中的方式加载该画笔。然后我将 R 通道(或 G 或 B 通道,因为它们都相等)复制到纹理的 Alpha 通道中。之后,我将画笔纹理的所有像素的 RGB 值设置为最大值。

所以现在你的画笔有一个 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);
}

返回画笔纹理;}

于 2010-07-16T21:20:57.223 回答
1

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

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

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

于 2010-05-28T19:08:18.410 回答
0

实际上这效果更好:

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
于 2010-06-09T19:57:46.103 回答
0

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

于 2010-07-04T06:44:58.283 回答
0
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

这是最好的答案。而且你必须为画笔充电。图片必须是alpha背景和椭圆。

于 2010-07-13T08:38:27.420 回答