Giả sử bạn đang tạo một kết cấu mới với glGenTextures
mỗi khi bạn gọi glTexImage2D
, bạn đang lãng phí bộ nhớ và rò rỉ nếu bạn không theo dõi tất cả các họa tiết bạn tạo ra. glTexImage2D
lấy dữ liệu đầu vào và lưu trữ bộ nhớ thẻ video. Tên kết cấu mà bạn liên kết trước khi gọi glTexImage2D
- cái mà bạn tạo ra với glGenTextures
là bộ xử lý cho đoạn bộ nhớ thẻ video đó.
Nếu kết cấu của bạn lớn và bạn đang cấp phát bộ nhớ mới để lưu trữ ngày càng nhiều bản sao của nó mỗi khi bạn sử dụng, thì bạn sẽ nhanh chóng hết bộ nhớ. Giải pháp là gọi glTexImage2D
một lần trong quá trình khởi tạo ứng dụng của bạn và chỉ gọi glBindTexture
khi bạn muốn sử dụng. Nếu bạn muốn thay đổi kết cấu khi bạn nhấp, chỉ gọi glBindTexture
và glTexImage2D
. Nếu hình ảnh mới của bạn có cùng kích thước với hình ảnh trước đó, bạn có thể gọi glTexSubImage2D
để yêu cầu OpenGL ghi đè lên dữ liệu hình ảnh cũ thay vì xóa hình ảnh đó và tải lên hình ảnh mới.
CẬP NHẬT
Để đối phó với mã mới của bạn, tôi đang cập nhật câu trả lời của tôi với một câu trả lời cụ thể hơn. Bạn đang xử lý kết cấu OpenGL theo cách sai hoàn toàn Kết quả của glGenTextures
là GLuint[]
và không phải là String
hoặc char[]
. Đối với mọi kết cấu bạn tạo ra với glGenTextures
, OpenGL cung cấp cho bạn trở lại một tay cầm (như một số nguyên không dấu) cho một kết cấu. Tay cầm này lưu trữ trạng thái bạn cung cấp cho nó glTexParameteri
cũng như một đoạn bộ nhớ trên cạc đồ họa nếu bạn cung cấp dữ liệu đó với glTexImage[1/2/3]D
. Bạn có thể lưu trữ bộ xử lý và gửi dữ liệu mới khi muốn cập nhật. Nếu bạn ghi đè lên tay cầm hoặc quên nó, dữ liệu vẫn nằm trên card đồ họa nhưng bạn không thể truy cập nó. Bạn cũng đang yêu cầu OpenGL tạo ra 3 hoạ tiết khi bạn chỉ cần 1.
Có kích thước cố định, bạn có thể cập nhật kết cấu bằng glTexSubImage2D
thay vì glTexImage2D
. Dưới đây là mã của bạn được sửa đổi để tránh rò rỉ bộ nhớ khỏi sự cố này:
texture_data = new GLubyte[width*height]();
GLuint texname; //handle to a texture
glGenTextures(1, &texname); //Gen a new texture and store the handle in texname
//These settings stick with the texture that's bound. You only need to set them
//once.
glBindTexture(GL_TEXTURE_2D, texname);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//allocate memory on the graphics card for the texture. It's fine if
//texture_data doesn't have any data in it, the texture will just appear black
//until you update it.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, texture_data);
...
//bind the texture again when you want to update it.
glBindTexture(GL_TEXTURE_2D, texname);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, texture_data);
...
//When you're done using the texture, delete it. This will set texname to 0 and
//delete all of the graphics card memory associated with the texture. If you
//don't call this method, the texture will stay in graphics card memory until you
//close the application.
glDeleteTextures(1, &texname);
Mã thực tế sẽ hữu ích khi theo dõi sự cố này. –
@NicolBolas, tôi đã putted mã, nhờ đã đề cập +1 – Shan