Tùy thuộc vào việc xây dựng GLEW đang được sử dụng phương pháp kín nước là gọi glewInit
sau mỗi và mọi ngữ cảnh thay đổi!
Với các con trỏ hàm X11/GLX là bất biến.
Nhưng trong con trỏ hàm OpenGL của Windows thì cụ thể cho từng ngữ cảnh. Một số bản xây dựng của GLEW là đa ngữ cảnh, trong khi những người khác thì không. Vì vậy, để bao gồm trường hợp đó, về mặt kỹ thuật bạn phải gọi nó, mọi lúc bối cảnh đã thay đổi.
(EDIT: do yêu cầu làm rõ)
cho mỗi cửa sổ (ví dụ, mỗi OpenGL Rendering Context)?
Điều đầu tiên trước tiên: ngữ cảnh OpenGL không được gắn với cửa sổ. Nó là hoàn toàn tốt để có một cửa sổ duy nhất nhưng nhiều bối cảnh dựng hình. Trong Microsoft Windows, điều quan trọng đối với OpenGL là bối cảnh thiết bị (DC) được liên kết với một cửa sổ. Nhưng nó cũng hoạt động theo cách khác vòng: Bạn có thể có một ngữ cảnh OpenGL duy nhất, nhưng nhiều cửa sổ sử dụng nó (miễn là pixelformat của cửa sổ tương thích với ngữ cảnh OpenGL).
Vì vậy, đây là hợp pháp:
HWND wnd = create_a window()
HDC dc = GetDC(wnd)
PIXELFORMATDESCRIPTOR pf = select_pixelformat();
SetPixelFormat(dc, pf);
HGLRC rc0 = create_opengl_context(dc);
HGLRC rc1 = create_opengl_context(dc);
wglMakeCurrent(dc, rc0);
draw_stuff(); // uses rc0
wglMakeCurrent(dc, rc1);
draw_stuff(); // uses rc1
Và như vậy là này
HWND wnd0 = create_a window()
HDC dc0 = GetDC(wnd)
HWND wnd1 = create_a window()
HDC dc1 = GetDC(wnd)
PIXELFORMATDESCRIPTOR pf = select_pixelformat();
SetPixelFormat(dc0, pf);
SetPixelFormat(dc1, pf);
HGLRC rc = create_opengl_context(dc0); // works also with dc1
wglMakeCurrent(dc0, rc);
draw_stuff();
wglMakeCurrent(dc1, rc);
draw_stuff();
Đây là nơi các phần mở rộng nhập hình ảnh. Một hàm như glActiveTexture
không phải là một phần của đặc tả OpenGL đã được gắn vào Giao diện nhị phân ứng dụng Windows (ABI). Do đó bạn phải có một con trỏ hàm vào nó khi chạy. Đó là những gì GLEW làm. Bên trong nó trông giống như thế này:
Đầu tiên nó định nghĩa các kiểu cho con trỏ hàm, khai báo chúng dưới dạng biến extern và sử dụng một chút ma thuật tiền xử lý để tránh xung đột không gian tên.
typedef void (*PFNGLACTIVETEXTURE)(GLenum);
extern PFNGLACTIVETEXTURE glew_ActiveTexture;
#define glActiveTexture glew_ActiveTexture;
Trong glewInit
các biến con trỏ hàm được thiết lập để các giá trị thu được sử dụng wglGetProcAddress
(vì lợi ích của khả năng đọc tôi bỏ qua đúc loại).
int glewInit(void)
{
/* ... */
if(openglsupport >= gl1_2) {
/* ... */
glew_ActiveTexture = wglGetProcAddress("glActiveTexture");
/* ... */
}
/* ... */
}
Bây giờ là phần quan trọng: wglGetProcAddress
tác phẩm với bối cảnh render OpenGL đó là hiện tại thời điểm gọi. Vì vậy, bất kỳ điều gì xảy ra với cuộc gọi cuối cùng wglMakeCurrent
được thực hiện trước đó. Như đã giải thích, các con trỏ hàm mở rộng được gắn với ngữ cảnh OpenGL của chúng và các bối cảnh OpenGL khác nhau có thể cung cấp các con trỏ hàm khác nhau cho cùng một hàm.
Vì vậy, nếu bạn làm điều này
wglMakeCurrent(…, rc0);
glewInit();
wglMakeCurrent(…, rc1);
glActiveTexture(…);
nó có thể thất bại. Vì vậy, nói chung, với GLEW, mọi cuộc gọi tới wglMakeCurrent
phải được theo sau bởi glewInit
. Một số bản xây dựng của GLEW là đa ngữ cảnh giác và làm điều này trong nội bộ. Những người khác thì không. Tuy nhiên, hoàn toàn an toàn khi gọi số glewInit
nhiều lần, vì vậy, cách an toàn là gọi nó, chỉ để chắc chắn.
Nhưng tôi vẫn chưa hiểu đầy đủ. Bạn có thể giải thích thêm một chút về ngữ cảnh "thay đổi" không? –
@ChanggongZhang: xem cập nhật của tôi. – datenwolf
Tôi chỉ nhận thấy rằng glew cũng cung cấp [glew32mx.lib, glew32mx.dll]. Điều này có nghĩa là Nếu tôi muốn tạo một ứng dụng nhiều cửa sổ, tôi nên sử dụng glew32mx.dll thay vì glew32.dll? Và một câu hỏi tiếp theo khác. Bạn có thể @datenwolf cung cấp ví dụ ứng dụng thực sự cho nhiều DC-single-RC & single-DC-nhiều-RC không? –