2011-08-25 22 views
20

Tôi cần phải khởi tạo kết cấu OpenGL 2D với số không.Làm thế nào để khởi tạo hiệu quả kết cấu bằng số không?

Tại sao? Tôi kết xuất với texture này bằng OpenCL. Khoảng, giai đoạn render là:

  1. Tạo texture RGBA, khởi tạo với số không (vì vậy nó có chứa điểm ảnh trong suốt màu đen)
  2. OpenCL: màu tính toán của pixel mà một số đối tượng có thể nhìn thấy và viết chúng vào kết cấu này
  3. OpenGL: thêm ánh xạ môi trường vào các pixel trong suốt và hiển thị hình ảnh cuối cùng

Do đó, tôi không cần chuyển bất kỳ dữ liệu họa tiết thực tế nào đến glTexImage2d. Nhưng theo spec, khi tôi vượt qua dữ liệu = NULL, bộ nhớ kết cấu được cấp phát nhưng không được khởi tạo.

Phân bổ bộ nhớ phía máy khách đầy zeroes và chuyển đến glTexImage2D không phải là một lựa chọn rất tốt mặc dù chỉ có một người tôi có thể nghĩ đến.

EDIT: Tôi thực sự muốn chỉ init thành phần alpha (RGB sẽ nhận được overriden anyway), nhưng tôi nghi ngờ điều này làm cho tình hình dễ dàng hơn.

Trả lời

32

Có một số cách để làm điều này:

1: Cho một chiều rộng và chiều cao cho một kết cấu:

std::vector<GLubyte> emptyData(width * height * 4, 0); 
glBindTexture(GL_TEXTURE_2D, texture); 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, &emptyData[0]); 

Đối với hiệu quả tối đa, bạn nên để lại một số thời gian giữa khi bạn gọi này và khi OpenCL bắt đầu công việc của mình.

2: Gắn nó vào một FBO và sử dụng glClearBuffer.

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); 
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); //Only need to do this once. 
glDrawBuffer(GL_COLOR_ATTACHMENT0); //Only need to do this once. 
GLuint clearColor[4] = {0, 0, 0, 0}; 
glClearBufferuiv(GL_COLOR, 0, clearColor); 

Điều này có vẻ nhanh hơn vì không có CPU-GPU DMA. Nhưng sự ràng buộc và không ràng buộc của các FBO có thể dẫn đến sự thiếu hiệu quả. Thế lần sau, nó có thể không được nữa. Hồ sơ nó để đảm bảo.

Lưu ý rằng tính năng này chỉ hoạt động đối với các định dạng hình ảnh có thể được sử dụng làm mục tiêu hiển thị. Vì vậy, không phải kết cấu nén.

3: Với đủ trình điều khiển, bạn có thể sử dụng ARB_clear_texture mở rộng mới:

glClearTexImage(texture, 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor); 

Lưu ý rằng điều này chỉ làm cho các định dạng hình ảnh mà dữ liệu có thể được cung cấp bởi standard pixel transfers. Vì vậy, không phải định dạng nén.

+0

Không bao giờ nghe nói về 'glClearBuffer'. Đây có phải là phiên bản mới không? Liệu nó có bất kỳ lợi thế hơn 'glClear' (hoặc là sau này thậm chí không được chấp nhận) ?. –

+1

@Christian: Lợi thế chính của ClearBuffer là bạn có thể xóa các bộ đệm cụ thể. Nếu bạn có nhiều bộ đệm trong bộ đệm khung, nhiều mục tiêu hiển thị, thì bạn có thể muốn xóa các bộ đệm khác nhau thành các màu khác nhau. Hay không rõ ràng chút nào. Bạn không thể làm điều đó với 'glClear'; nó xóa tất cả các bộ đệm với cùng một màu sắc rõ ràng. 'glClear' không được dùng nữa, và' glClearBuffer' xuất phát từ GL 3.0 (không có phần mở rộng cho nó). –

+1

Lưu ý rằng glClearTexImage chỉ hoạt động nếu lưu trữ kết cấu đã được phân bổ trước đó, sử dụng lệnh gọi đến glTexImage * hoặc glTexStorage *. Đơn giản chỉ cần tạo texture bằng cách sử dụng glBindTexture là không đủ. Nhưng điều này cũng áp dụng cho glTexSubImage2D, tất nhiên. – rdb

1

Có thể bạn có thể đặt kết cấu làm mục tiêu hiển thị cho lần truyền đầu tiên và vẽ một màu đen nguyên thủy. Nó có thể nhanh hơn vì không có bộ nhớ truyền giữa ram và card đồ họa.

+0

Điểm tốt. Nhưng tôi có thể quản lý để thiết lập alpha = 0 với phương pháp này? Tôi thực sự muốn init chỉ alpha, tôi không bận tâm với các thành phần RGB. – jirkamat

+3

Sử dụng glClearColor và glClear có thể tốt hơn. glClearColor chấp nhận alpha. – neodelphi

5

Chỉ cần lưu ý: Tiện ích mở rộng GL_ARB_clear_texture (lõi trong 4.4) mới cụ thể giải quyết vấn đề này.

+0

Điều này đúng, nhưng một lời cảnh báo: Bạn chắc chắn muốn lập hồ sơ này. Trên hệ thống của tôi, glClearTexture là MUCH chậm hơn so với sử dụng một framebuffer và glClear/glClearBuffer. – Jagoly

+0

@Jagoly bạn đã định cấu hình đúng cách sử dụng truy vấn hẹn giờ GPU chưa? – Ancurio

+0

Không, chỉ cần sử dụng khung thời gian. Nó không chỉ là một chút chậm hơn, mặc dù; clearTexture (hai cuộc gọi, rgb8 + độ sâu 24 bit) mất hơn ba lần so với độ rõ ràng. Tôi đã thiết lập bộ đệm khung. Sự khác biệt thậm chí còn lớn hơn chỉ cho độ sâu (5x). – Jagoly

0
  1. glTexSubImage được làm đầy với toàn bộ hình ảnh:

    GLfloat* pData = new GLfloat[1024*768*4]; 
    memset(pData, 0x00, 1024*768*4*sizeof(GLfloat)); 
    glBindTexture(GL_TEXTURE_2D, m_ImageTex); 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 768, GL_RGBA, GL_FLOAT, pData); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    delete pData; 
    
  2. sử dụng Pixel Buffer để sao chép dữ liệu từ gpu, phương pháp này là nhanh hơn và tốt hơn

    i. init PBO

    glGenBuffers(1, &m_PixelBuffer); 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_PixelBuffer); 
    glBufferData(GL_PIXEL_UNPACK_BUFFER, SCREEN_WIDTH*SCREEN_HEIGHT*4*sizeof(GLfloat), NULL, GL_STATIC_DRAW); 
    GLfloat* pData = nullptr; 
    pData = (GLfloat*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); 
    memset(pData, 0x00, 1024*768*4*sizeof(GLfloat)); 
    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); 
    

    ii.

    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_PixelBuffer); 
    glBindTexture(GL_TEXTURE_2D, m_ImageTex); 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGBA, GL_FLOAT, NULL); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 
    
Các vấn đề liên quan