2010-05-08 25 views
2

試圖爲iPhone寫一個簡單的繪畫程序,並且我使用Apple的glPaint樣本作爲指南。唯一的問題是,繪畫不適用於白色背景,因爲白+顏色=白。我已經嘗試了不同的混合功能,但是無法使用正確的設置和/或畫筆組合來完成這項工作。我已經看到類似的帖子關於這個問題,但沒有答案。有誰知道這可能如何工作?基於Apple的'glPaint'在白色背景上的OpenGL繪圖程序 - 如何混合?

編輯:
我甚至不真透明效果,在這一點上,如果我能畫實線與圓端我會很高興。

回答

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 

正如你所看到的,這導致在一個不錯的紫色,這是藍色的組合和紅色。您可以調整添加劑的比例以減去邏輯來模擬油漆混合的程度。

希望有幫助! =)

+0

不錯的想法...我已經嘗試過,但無法讓它工作,例如,如果我用100%不透明度的紅色(255,0,0)繪製,然後用藍色(0,0,255),你會期望它是藍色的,但它實際上是黑色的(0,0,0) – Adam 2010-05-08 03:36:20

+0

@Adam:嗯。這是真的。我將編輯。 – 2010-05-08 05:09:27

+0

又一個好主意!我也玩過這個,但是opengl畫筆很有趣 - 在形狀區域之外被解釋爲黑色,50%的白色背景+ 50%的黑色=灰色框內的漂亮的形狀。我會繼續試驗和更新,如果我找到合適的組合......但理論上我認爲這是一個很好的答案,所以我會給你一個大複選標記 – Adam 2010-05-08 06:10:10

1

我碰到類似的東西。下面的混合函數調用爲我解決了它,而沒有任何複雜的數學。

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

在你的glDraw調用之前添加它,你應該可以使用任何紋理作爲畫筆繪製。

+0

這是否在白色背景上工作?我嘗試了這些設置,並且遇到了同樣的問題,那就是我只是在白色的頂部添加了一種顏色,而這種顏色變成了白色。 – Adam 2010-05-30 20:06:05

+0

是的,我做了一個glClear設置一切爲白色,然後這些設置讓我在任何顏色的白色背景上繪製,而不與白色合併。 – 2010-06-02 20:08:35

+0

我用這個代碼。也許我的畫筆紋理不好,但在我的情況下,我的畫筆紋理周圍有灰色的輪廓..你能告訴我,你用什麼樣的畫筆紋理?正如我所瞭解的白色背景畫筆紋理在透明背景上應該是白色的。這樣對嗎? – OgreSwamp 2010-07-06 10:09:12

0

其實這部作品甚至更好:

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); 
+0

你可以向我發送代碼嗎?我嘗試了這兩個,但它仍然沒有工作......要麼它只是白色的,或刷子的邊緣是錯誤的,我已經嘗試了100個組合:( – Adam 2010-06-14 05:11:09

+0

爲什麼不發佈你的代碼,讓我們調試我的代碼是在NDA下使用的。 – 2010-06-22 19:50:17

0

示例代碼GLPaint用於glBlendFunc(GL_SRC_ALPHA, GL_ONE)和功能- (id)initWithCoder:(NSCoder*)coder。所以當顏色爲白色glBlendFunc(GL_SRC_ALPHA, GL_ONE)模式,所有其他的顏色不會被看到。 我也想解決它。

0
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); 

這是最好的答案。你必須充電刷圖片。圖片必須是一個阿爾法背景,而橢圓。

2

是的,我有同樣的問題。刷子的邊緣比他們應該是黑暗的。事實證明,蘋果的api預先將α乘以rgb頻道。

所以我通過在Photoshop中製作灰度畫筆,只用rgb值並且沒有alpha通道。這應該看起來像你想要你的畫筆用白色代表全色色素,黑色代表沒有色素沉着。 我按照在蘋果的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); 
} 

回報brushTexture; }

+0

可以通過改變這條線來修正預乘問題嗎?brushContext = CGBitmapContextCreate(brushData,width,width,8,width * 4,CGImageGetColorSpace(brushImage),kCGImageAlphaPremultipliedLast); – Adam 2012-06-12 23:18:16

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

默認的混合功能,刷的圖像似乎只是工作。

+0

這是glClearColor(1.0,1.0,1.0,0.0); – 2011-04-14 15:01:20

+0

這對我不起作用......默認的混合功能就像添加光源一樣工作,所以白色+任何顏色=白色 – Adam 2012-06-12 23:05:16