mỗi phần giới thiệu và mẫu mà tôi có thể tìm thấy có vẻ như sử dụng GLUT hoặc một số khung công tác khác để "khởi tạo" OpenGL. Có cách nào để khởi tạo OpenGL chỉ với những gì có sẵn trong GL và GLU? Nếu không, thì GLUT làm điều gì là không thể nếu không có nó?Khởi tạo OpenGL mà không cần GLUT
Trả lời
Như lưu ý, mã để tạo và ràng buộc ngữ cảnh là cụ thể cho từng nền tảng cửa sổ.
Dưới đây là một số chức năng để giúp bạn bắt đầu về khởi tạo OpenGL trên nền tảng cụ thể:
Windows (một hướng dẫn là here)
- wglCreateContext (HDC)
Mac OS X - OS X có ba lựa chọn cơ bản: Carbon, Ca cao và Lớp Đồ họa Lõi cơ bản
- The entire guide for Mac OS X OpenGL development
- Carbon: aglCreateContext
- Cocoa: Tạo (hoặc lớp) một NSOpenGLView. Họ tạo ra bối cảnh riêng của họ, và bạn có thể đọc tài liệu phương pháp của họ để tìm cách làm cho nó hiện tại.
- CoreGraphicsLayer: CGLCreateContext
Linux
- glx: glXCreateContext
Cảm ơn, đây là những hữu ích. Bây giờ tôi nhận ra rằng vấn đề của tôi là cụ thể cho Windows bên cạnh mã thay vì chỉ OpenGL (tức là cố gắng để OpenGL hoạt động trên đầu trang - hoặc bên cạnh? - GDI +) –
Bạn không phân lớp NSOpenGLView, bạn phân lớp NSView và sử dụng NSOpenGLContext và NSPixelFormat để linh hoạt hơn (và bạn chỉ sử dụng NSOpenGLView cho những thứ rất đơn giản). – mk12
Ngoài ra, lưu ý rằng Carbon là một kết thúc chết (không hỗ trợ 64 bit) và CGL không thể tạo cửa sổ, vì vậy OS X sử dụng NSGL cho cửa sổ Cocoa, menu vv và CGL cho các ứng dụng toàn màn hình. – mk12
Bạn có thể lấy GLUT source code và xem mã init cho bất kỳ nền tảng nào bạn quan tâm.
Dưới đây là một giới thiệu cơ bản và tốt để làm thế nào bạn khởi tạo OpenGL (giả sử cửa sổ) mà không sử dụng GLUT:
Như Luke nói rằng, nếu bạn không muốn sử dụng dư thừa, bạn cần thông tin cụ thể về hệ điều hành bạn đang phát triển. Sử dụng GLUT sẽ làm cho mã của bạn dễ dàng hơn để chuyển.
Mẫu này sử dụng glut? –
GL là một API và GLU là một thư viện tiện ích trên đầu trang của GL. Nó hoàn toàn độc lập với hệ điều hành.
Khởi tạo OpenGL và tìm nạp tiện ích mở rộng là các hoạt động phụ thuộc nền tảng. Do đó bạn không thể làm gì với OpenGL một mình.
GLUT không đủ nhanh và thư viện cực kỳ kém, và chỉ có nó mới khởi tạo ngữ cảnh opengl và cung cấp một số mô-đun đầu vào chuột/bàn phím nguyên thủy để giúp bạn tiếp tục.
Win32 cũng cung cấp các công cụ để khởi chạy ngữ cảnh opengl. Đối với Linux bạn có thể kiểm tra GLX. Ngoài ra, nếu bạn muốn một cách độc lập hệ thống để làm điều đó, sau đó bạn có thể kiểm tra SDL. Đối với các ngôn ngữ lập trình khác nhau, có thể có các tiện ích cung cấp cho bạn một API nền tảng độc lập cho máy tính để bàn.
Bạn có thể kiểm tra nguồn gốc của Galaxy Lực lượng V2, http://www.galaxy-forces.com/
Nó thực hiện các lớp học cho OpenGL không sử dụng GLUT hoặc các thư viện khác trên Windows, Mac, và Linux. Sử dụng mã nền tảng gốc, tất cả miền công cộng.
GLX tối thiểu dụ Runnable
Phỏng theo here.
Cũng đề cập đến đầu vào bàn phím.
Compile với:
gcc glx.c -lGLU -lGL -lX11
Tested trong Ubuntu 14.04.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#define GL_GLEXT_PROTOTYPES
#define GLX_GLXEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
struct MyWin {
Display *display;
Window win;
int displayed;
int width;
int height;
};
const int WIN_XPOS = 256;
const int WIN_YPOS = 64;
const int WIN_XRES = 320;
const int WIN_YRES = 320;
const int NUM_SAMPLES = 4;
struct MyWin Win;
double elapsedMsec(const struct timeval *start, const struct timeval *stop) {
return ((stop->tv_sec - start->tv_sec) * 1000.0 +
(stop->tv_usec - start->tv_usec)/1000.0);
}
void displayCB() {
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glEnd();
glFlush();
glXSwapBuffers(Win.display, Win.win);
}
void keyboardCB(KeySym sym, unsigned char key, int x, int y,
int *setting_change) {
switch (tolower(key)) {
case 27:
exit(EXIT_SUCCESS);
break;
case 'k':
printf("You hit the 'k' key\n");
break;
case 0:
switch (sym) {
case XK_Left :
printf("You hit the Left Arrow key\n");
break;
case XK_Right :
printf("You hit the Right Arrow key\n");
break;
}
break;
}
}
void reshapeCB(int width, int height) {
Win.width = width;
Win.height = height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode(GL_MODELVIEW);
}
/* Try to find a framebuffer config that matches
* the specified pixel requirements.
*/
GLXFBConfig chooseFBConfig(Display *display, int screen) {
static const int Visual_attribs[] = {
GLX_X_RENDERABLE , True,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
GLX_RED_SIZE , 8,
GLX_GREEN_SIZE , 8,
GLX_BLUE_SIZE , 8,
GLX_ALPHA_SIZE , 8,
GLX_DEPTH_SIZE , 24,
GLX_STENCIL_SIZE , 8,
GLX_DOUBLEBUFFER , True,
GLX_SAMPLE_BUFFERS, 1,
GLX_SAMPLES , 4,
None
};
int attribs [ 100 ] ;
memcpy(attribs, Visual_attribs, sizeof(Visual_attribs));
GLXFBConfig ret = 0;
int fbcount;
GLXFBConfig *fbc = glXChooseFBConfig(display, screen, attribs, &fbcount);
if (fbc) {
if (fbcount >= 1)
ret = fbc[0];
XFree(fbc);
}
return ret;
}
GLXContext createContext(Display *display, int screen,
GLXFBConfig fbconfig, XVisualInfo *visinfo, Window window) {
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*,
GLXFBConfig, GLXContext, int, const int*);
/* Verify GL driver supports glXCreateContextAttribsARB() */
/* Create an old-style GLX context first, to get the correct function ptr. */
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
GLXContext ctx_old = glXCreateContext(display, visinfo, 0, True);
if (!ctx_old) {
printf("Could not even allocate an old-style GL context!\n");
exit(EXIT_FAILURE);
}
glXMakeCurrent (display, window, ctx_old) ;
/* Verify that GLX implementation supports the new context create call */
if (strstr(glXQueryExtensionsString(display, screen),
"GLX_ARB_create_context") != 0)
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB");
if (!glXCreateContextAttribsARB) {
printf("Can't create new-style GL context\n");
exit(EXIT_FAILURE);
}
/* Got the pointer. Nuke old context. */
glXMakeCurrent(display, None, 0);
glXDestroyContext(display, ctx_old);
/* Try to allocate a GL 4.2 COMPATIBILITY context */
static int Context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
/*GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, */
/*GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, */
/*GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB, */
None
};
GLXContext context = glXCreateContextAttribsARB(display, fbconfig, 0,
True, Context_attribs);
/* Forcably wait on any resulting X errors */
XSync(display, False);
if (!context) {
printf("Failed to allocate a GL 4.2 context\n");
exit(EXIT_FAILURE);
}
printf("Created GL 4.2 context\n");
return context;
}
void createWindow() {
/* Init X and GLX */
Win.displayed = 0;
Display *display = Win.display = XOpenDisplay(":0.0");
if (!display)
printf("Cannot open X display\n");
int screen = DefaultScreen(display);
Window root_win = RootWindow(display, screen);
if (!glXQueryExtension(display, 0, 0))
printf("X Server doesn't support GLX extension\n");
/* Pick an FBconfig and visual */
GLXFBConfig fbconfig = chooseFBConfig(display, screen);
if (!fbconfig) {
printf("Failed to get GLXFBConfig\n");
exit(EXIT_FAILURE);
}
XVisualInfo *visinfo = glXGetVisualFromFBConfig(display, fbconfig);
if (!visinfo) {
printf("Failed to get XVisualInfo\n");
exit(EXIT_FAILURE);
}
printf("X Visual ID = 0x%.2x\n", (int)visinfo->visualid);
/* Create the X window */
XSetWindowAttributes winAttr ;
winAttr.event_mask = StructureNotifyMask | KeyPressMask ;
winAttr.background_pixmap = None ;
winAttr.background_pixel = 0 ;
winAttr.border_pixel = 0 ;
winAttr.colormap = XCreateColormap(display, root_win,
visinfo->visual, AllocNone);
unsigned int mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
Window win = Win.win = XCreateWindow (display, root_win,
WIN_XPOS, WIN_YPOS,
WIN_XRES, WIN_YRES, 0,
visinfo->depth, InputOutput,
visinfo->visual, mask, &winAttr) ;
XStoreName(Win.display, win, "My GLX Window");
/* Create an OpenGL context and attach it to our X window */
GLXContext context = createContext(display, screen, fbconfig, visinfo, win);
if (! glXMakeCurrent(display, win, context))
printf("glXMakeCurrent failed.\n");
if (! glXIsDirect (display, glXGetCurrentContext()))
printf("Indirect GLX rendering context obtained\n");
/* Display the window */
XMapWindow(display, win);
if (! glXMakeCurrent(display, win, context))
printf("glXMakeCurrent failed.\n");
printf("Window Size = %d x %d\n", WIN_XRES, WIN_YRES);
printf("Window Samples = %d\n", NUM_SAMPLES);
}
void processXEvents(Atom wm_protocols, Atom wm_delete_window) {
int setting_change = 0;
while (XEventsQueued(Win.display, QueuedAfterFlush)) {
XEvent event;
XNextEvent(Win.display, &event);
if(event.xany.window != Win.win)
continue;
switch (event.type) {
case MapNotify:
{
Win.displayed = 1;
break;
}
case ConfigureNotify:
{
XConfigureEvent cevent = event.xconfigure;
reshapeCB(cevent.width, cevent.height);
break;
}
case KeyPress:
{
char chr;
KeySym symbol;
XComposeStatus status;
XLookupString(&event.xkey, &chr, 1, &symbol, &status);
keyboardCB(symbol, chr, event.xkey.x, event.xkey.y,
&setting_change);
break;
}
case ClientMessage:
{
if (event.xclient.message_type == wm_protocols &&
(Atom)event.xclient.data.l[0] == wm_delete_window) {
exit(EXIT_SUCCESS);
}
break;
}
}
}
}
void mainLoop() {
/* Register to receive window close events (the "X" window manager button) */
Atom wm_protocols = XInternAtom(Win.display, "WM_PROTOCOLS" , False);
Atom wm_delete_window = XInternAtom(Win.display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(Win.display, Win.win, &wm_delete_window, True);
while (1) {
/* Redraw window (after it's mapped) */
if (Win.displayed)
displayCB();
/* Update frame rate */
struct timeval last_xcheck = {0, 0};
struct timeval now;
gettimeofday(&now, 0);
/* Check X events every 1/10 second */
if (elapsedMsec(&last_xcheck, &now) > 100) {
processXEvents(wm_protocols, wm_delete_window);
last_xcheck = now;
}
}
}
int main(int argc, char *argv[]) {
Win.width = WIN_XRES;
Win.height = WIN_YRES;
createWindow();
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
printf("Valid keys: Left, Right, k, ESC\n");
printf("Press ESC to quit\n");
mainLoop();
return EXIT_SUCCESS;
}
Một luôn có thể mở ra nguồn gốc của FreeGlut để xem nó như thế nào thực hiện mỗi chức năng dư thừa, nhưng sẽ thấp hơn so với mức GLX có khả năng hardcore.
EGL
Trông giống như một Khronos thay thế tiêu chuẩn để GLX, hiện thường được sử dụng với OpenGL ES.
https://cgit.freedesktop.org/mesa/demos/tree/src/egl chứa các ví dụ sử dụng thực hiện Mesa, nhưng tôi vẫn chưa được quản lý để làm cho họ làm việc:
git checkout mesa-demos-8.1.0
./autogen.sh
./configure
make
Không với:
/work/git/mesa-demos/src/egl/opengl/demo1.c:26: undefined reference to `eglGetScreensMESA'
Nhưng Ubuntu 14.04 có es2gears
trong gói mesa-utils-extra
, vì vậy phải có một cách.
Xem thêm: What is EGL And How Can I Use It
- 1. Căn giữa cửa sổ OpenGL với GLUT
- 2. Đọc pixel từ Ứng dụng OpenGL/GLUT
- 3. Biên dịch OpenGL và GLUT OSX
- 4. Văn bản đơn giản trong OpenGL (không có GLUT)
- 5. GLUT có chết không?
- 6. Bạn có thể tạo ngữ cảnh OpenGL mà không cần mở một cửa sổ không?
- 7. OpenGL Hello World trên Mac mà không cần XCode
- 8. Có thể khởi động hạt nhân Linux mà không cần tạo hình ảnh initrd không?
- 9. Có thể khởi tạo lớp Ruby mà không gọi khởi tạo không?
- 10. Khởi chạy Ruby mà không cần tiền tố "Ruby"
- 11. Khởi động lại nginx mà không cần sudo?
- 12. Khởi động ứng dụng android mà không cần hoạt động
- 13. Tạo một kết xuất chuỗi Java mà không cần khởi động lại.
- 14. có được khối khởi tạo tĩnh để chạy trong một java mà không cần nạp lớp
- 15. Làm thế nào để có được loại lớp mà không cần khởi tạo đối tượng?
- 16. Kích thước bộ sưu tập đếm ngủ đông mà không cần khởi tạo
- 17. Tạo dịch vụ WCF mà không cần tệp .svc
- 18. khởi động lại ứng dụng mà không cần khởi động lại máy chủ?
- 19. Làm thế nào để tạo cơ sở dữ liệu từ schema.rb mà không cần khởi tạo Rails?
- 20. Tạo DMG mà không cần thêm không gian
- 21. Cần xóa khóa MySQL InnoDB mà không cần khởi động lại cơ sở dữ liệu
- 22. GLUT trên OS X với OpenGL 3.2 Cấu hình cốt lõi
- 23. Việc khởi tạo con trỏ này có cần thiết không?
- 24. Khởi tạo NCurses mà không xóa màn hình
- 25. Sao chép kết cấu vào bộ đệm màn hình mà không cần vẽ quad (opengl)
- 26. OpenGL ES: đổ bóng phẳng mà không cần sao chép đỉnh?
- 27. Làm thế nào để đóng cửa sổ GLUT mà không chấm dứt ứng dụng?
- 28. wxWidgets: Cách khởi tạo wxApp mà không cần sử dụng macro và không nhập vòng lặp ứng dụng chính?
- 29. Sử dụng con lăn chuột trong GLUT
- 30. Sử dụng phông chữ bitmap GLUT
Không ai đề cập [EGL] (http://www.khronos.org/egl)? Đó là một tiêu chuẩn Khronos cho interop giữa hệ điều hành và các API như OpenGL, nhằm hợp nhất những thứ như vậy. Tuy nhiên, IDK đã được hỗ trợ rộng đến mức nào. – Kos
chỉ dành cho Windows. – rotoglup
Yup, nhưng nó vẫn mang tính hướng dẫn. :-) Cảm ơn! –