2010-07-06 24 views
5

Tôi đang phát triển ứng dụng vẽ tranh. Tôi đã cố gắng làm điều đó với thuật toán CoreGraphics/Quartz 2D và vẽ đường cong khá chậm. Vì vậy, chúng tôi đã quyết định chuyển sang OpenGL ES. Tôi chưa bao giờ có bất kỳ trải nghiệm OpenGL nào, vì vậy tôi đã tìm thấy ví dụ glPaint từ táo và bắt đầu chơi với nó.Ứng dụng vẽ iPhone (dựa trên glPaint). Trộn với nền trắng

Tôi đã thay đổi phương thức erase làm nền trắng. Làm thế nào tôi bị mắc kẹt với bàn chải và pha trộn. Trong ví dụ, Apple sử dụng texture "white on black" cho brush (đầu tiên trên pic bên dưới). Nhưng nó không hiệu quả đối với tôi (tôi chơi với các chế độ hoà trộn khác nhau). Vì vậy, tôi đã quyết định sử dụng bàn chải khác nhau, nhưng tôi đã không tìm thấy cách thích hợp. Tôi đã tìm thấy một số câu hỏi về luồng ngăn xếp, nhưng tất cả chúng đều chưa được trả lời. Đây là một hình ảnh (từ một câu hỏi khác, nhờ vào Kevin Beimers). Results http://www.straandlooper.com/GLPaint.png

Vì vậy, câu hỏi là cách thực hiện nét như "mong muốn" trong ảnh. Và làm thế nào để pha trộn 2 nét gần gũi hơn với trải nghiệm thực tế đời sống (màu xanh trên màu vàng = màu xanh đậm).

Cảm ơn.

Có mã hiện tại (bit sửa đổi từ glPaint) cho bàn chải (từ initWithFrame phương pháp:.

// Make sure the image exists 
if(brushImage) { 
    // Allocate memory needed for the bitmap context 
    brushData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte)); 
    // Use the bitmatp creation function provided by the Core Graphics framework. 
    brushContext = CGBitmapContextCreate(brushData, width, width, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast); 
    // After you create the context, you can draw the image to the context. 
    CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (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); 
    // 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, brushData); 
    // Release the image data; it's no longer needed 
     free(brushData); 
    // Make the current material colour track the current color 
    glEnable(GL_COLOR_MATERIAL); 
    // Enable use of the texture 
    glEnable(GL_TEXTURE_2D); 
    // Set a blending function to use 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    // Enable blending 
    glEnable(GL_BLEND); 
    // Multiply the texture colour by the material colour. 
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

} 

//Set up 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); 




// Alpha blend each "dab" of paint onto background 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 


//glBlendFunc(GL_SRC_COLOR, GL_ONE); 
glEnable(GL_POINT_SPRITE_OES); 
glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE); 

self.brushScale = 3; 
self.brushStep = 3; 
self.brushOpacity = (1.0/1.5); 

glPointSize(width/brushScale); 

//Make sure to start with a cleared buffer 
needsErase = YES; 
[self erase]; 

Trả lời

18

Hãy bắt đầu bằng cách xác định loại pha trộn bạn đang tìm kiếm Có vẻ như bạn muốn đệm của bạn . để bắt đầu trắng và có màu sắc của bạn trộn tuân theo một subtractive color model cách dễ nhất để làm điều đó là để xác định kết quả của sự pha trộn C bàn chải qua C dst như:

C = C bàn chải × C dst

Chú ý rằng việc sử dụng phương trình này, kết quả của sự pha trộn màu vàng (1, 1, 0) và màu lục lam (0 , 1, 1) có màu xanh lá cây (0, 1, 0), đó là những gì bạn mong đợi.

Có bàn chải mờ dần ở các cạnh làm phức tạp mọi thứ một chút. Giả sử bây giờ bạn có một giá trị bàn chải opacity Một bàn chải -where Một bàn chải là 1, bạn muốn màu sắc bàn chải của bạn để pha trộn khả năng đầy đủ, và nơi Một bàn chải là 0, bạn muốn màu gốc vẫn còn.Bây giờ những gì bạn đang tìm kiếm là:

C = (C bàn chải × C dst) × Một bàn chải + C dst × (1 - A cọ)

Kể từ khi pha trộn trong kết quả OpenGL ES tính C = C src × S + C dst × D, chúng tôi có thể nhận được chính xác những gì chúng ta muốn nếu chúng ta làm cho thay sau :

C src = C bàn chải × Một bàn chải

Một src = Một bàn chải

S = C dst

D = (1-Một bàn chải)

Bây giờ chúng ta hãy nhìn vào những gì nó cần để thiết lập này lên trong OpenGL ES. Có 4 bước ở đây:

  1. Thay đổi màu nền thành trắng.

  2. Thay đổi kết cấu bàn chải thành kết cấu alpha.
    Theo mặc định, GLPaint tạo kết cấu bàn chải của nó dưới dạng kết cấu RGBA với hình dạng bàn chải được vẽ trong các kênh RGB, có phần hơi không trực quan. Vì lý do bạn sẽ thấy sau này, thay vào đó, hữu ích khi có hình dạng bàn chải trong kênh alpha.Cách tốt nhất để làm điều này là bằng cách vẽ hình dạng bàn chải trong màu xám với CG và tạo các kết cấu như GL_ALPHA thay vì:

    CGColorSpaceRef brushColorSpace = CGColorSpaceCreateDeviceGray(); 
    brushData = (GLubyte *) calloc(width * height, sizeof(GLubyte)); 
    brushContext = CGBitmapContextCreate(brushData, width, width, 8, width, brushColorSpace, kCGImageAlphaNone); 
    CGColorSpaceRelease(brushColorSpace); 
    

    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, brushData);   
    
  3. Thiết lập C src, Một src, SD.
    Sau khi chuyển sang một cấu trúc alpha, giả định rằng màu bàn chải của bạn vẫn đang được xác định bằng glColor4f, bạn sẽ thấy rằng mặc định OpenGL ES môi trường kết cấu sẽ cung cấp cho bạn điều này:

    C src = C bàn chải

    Một src = Một bàn chải

    Để có được nhân thêm bởi Một bàn chải cho C src, bạn sẽ cần phải thiết lập một chức năng tùy chỉnh bộ kết hợp trong môi trường kết cấu như sau (bạn có thể làm điều này trong chức năng khởi tạo cho PaintingView):

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA); 
    

    Thay đổi GL_TEXTURE_ENV_MODE đến GL_COMBINE cung cấp cho bạn C cọ × 0 (để xem tại sao đây là trường hợp, hãy đọc phần 3.7.12 trong số OpenGL ES 1.1 specification). Thay đổi GL_OPERAND0_RGB thành GL_SRC_ALPHA thay đổi cụm từ thứ hai trong phép nhân thành những gì chúng ta muốn.

    Để thiết lập SD, tất cả các bạn cần làm là thay đổi những yếu tố pha trộn (điều này có thể được thực hiện nơi các yếu tố pha trộn đã được thiết lập trước đó):

    glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); 
    
  4. Đảm bảo rằng bất kỳ sửa đổi nào đối với A cọ bên ngoài kết cấu bàn chải được phản ánh trên các kênh khác.
    Các sửa đổi ở trên đối với môi trường kết cấu chỉ tính đến phần của độ mờ của bút vẽ đến từ kết cấu cọ vẽ. Nếu bạn sửa đổi độ mờ của bút vẽ trong kênh alpha ở nơi khác (tức làbởi nhân rộng nó, như trong AppController), bạn phải chắc chắn rằng bạn thực hiện các thay đổi cùng với ba kênh khác:

    glColor4f(components[0] * kBrushOpacity, components[1] * kBrushOpacity, components[2] * kBrushOpacity, kBrushOpacity); 
    

Lưu ý rằng các nhược điểm để thực hiện bàn chải của bạn với một mô hình phối màu hấp thụ là rằng màu sắc chỉ có thể tối hơn, và nhiều lần vẽ cùng một màu trên bản thân nó cuối cùng có thể dẫn đến sự dịch chuyển màu nếu nó không phải là một trong những màu trừ chính (lục lam, đỏ tươi hoặc vàng). Nếu sau khi thực hiện điều này, bạn thấy rằng sự thay đổi màu sắc là không thể chấp nhận, hãy thử thay đổi kết cấu bàn chải với một kết cấu alpha như ở bước 2 và thay đổi các yếu tố pha trộn như sau:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

này sẽ cung cấp cho bạn bức tranh đơn giản màu bàn chải của bạn trên màu trắng, nhưng không có sự pha trộn thực tế của màu sắc (màu sắc bàn chải cuối cùng sẽ ghi đè lên nền).

+0

Cảm ơn bạn rất nhiều vì đã trả lời rất chi tiết! Tôi đã thử giải pháp của bạn và nó hoạt động. – OgreSwamp

+0

Tôi mới cho opengl nếu có thể bạn có thể chia sẻ mã – dineshprasanna

Các vấn đề liên quan