اول اینکه OpenGL چون چند-سکو هست تو سکو های مختلف دسترسی بهش مختلف هست .
توی Windows باید با توابع WGL به OpenGL دسترسی پیدا کنید . که توابع WGL در فایل opengl32.dll پیاده شدند .
توی Linux/Unix درواقع چندجور راه هست .در سیستم عامل های Linux معمولا از X برای مدیریت سیستم پنجره استفاده میشه و برای همین برای سیستم X یک Extension وجود داره به نام GLX .
معمولا وقتی Driver ( البته Driver های مربوط به X ) برای OpenGL نوشته میشه GLX هم داخلش پیاده سازی میکنن .
برای لینوکس شما باید به کتابخونه libGL.so برنامتون رو پیوند بدید .
حتما این فایل ها رو دانلود کن و داخل این مسیر /usr/include/GL/ کپیشون کن :
https://www.opengl.org/registry/api/GL/glext.h
https://www.opengl.org/registry/api/GL/glcorearb.h
https://www.opengl.org/registry/api/GL/glxext.h
https://www.opengl.org/registry/api/GL/wglext.h
خب حالا این کد یه پنجره خالی با X و یک Context نسخه 3.3 از نوع Core Profile درست میکنه و یه سری اطلاعات رو نمایش میده . البته تو این کد برای رسم تصاویر چیزی ننوشتم و بیشتر هدفش ساختن Context هست .
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/glcorearb.h>
#include <GL/glxext.h>
/*** Variables ***/
static const int attr [] = {
GLX_BUFFER_SIZE , 32 ,
GLX_DOUBLEBUFFER , True ,
GLX_STENCIL_SIZE , 8 ,
GLX_DEPTH_SIZE , 16 ,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_X_RENDERABLE , True ,
NULL , NULL ,
};
static const GLint gl_attr[] ={
GLX_CONTEXT_MAJOR_VERSION_ARB , 3,
GLX_CONTEXT_MINOR_VERSION_ARB , 3,
GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
// GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
NULL , NULL ,
};
Display* dsp = NULL;
GLXFBConfig* fb_get_cfg,*fb_choose_cfg;
XVisualInfo* visual_info = NULL;
int maj,min,fb_get_elements,fb_choose_elements,screen;
Window window,root_window;
XSetWindowAttributes window_attr;
Colormap cmap;
GLXContext context;
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
Bool direct;
GLint glmaj,glmin,f1,f2,f3;
static void create_context_default (void);
static void create_context_new (void);
static void create_context_arb (void);
static void load_func (void);
int main ()
{
/*** Initialization ***/
memset(&window_attr,0,sizeof(window_attr));
dsp = XOpenDisplay(NULL);
screen = DefaultScreen(dsp);
glXQueryVersion (dsp,&maj,&min);
fb_get_cfg = glXGetFBConfigs(dsp,screen,&fb_get_elements);
fb_choose_cfg = glXChooseFBConfig (dsp , 0 , attr , &fb_choose_elements);
visual_info = glXGetVisualFromFBConfig (dsp , fb_choose_cfg[0]);
root_window = RootWindow (dsp ,screen);
cmap = XCreateColormap (dsp , root_window ,visual_info->visual,AllocNone);
window_attr.colormap = cmap;
window_attr.border_pixel = 0;
window_attr.event_mask = StructureNotifyMask;
window = XCreateWindow (dsp , root_window , 0 , 0,640,480, 1 ,
visual_info->depth ,InputOutput , visual_info->visual ,
CWBackPixel|CWBorderPixel|CWColormap|CWEventMask ,&window_attr);
XMapWindow(dsp,window);
/*** OpenGL Context ***/
load_func();
// create_context_default();
create_context_arb();
// create_context_new();
direct = glXIsDirect(dsp,context);
PFNGLGETINTEGERVPROC _glGetIntegerv;
_glGetIntegerv = glXGetProcAddressARB ((const GLubyte*) "glGetIntegerv");
_glGetIntegerv(GL_MAJOR_VERSION,&glmaj);
_glGetIntegerv(GL_MINOR_VERSION,&glmin);
_glGetIntegerv(GL_CONTEXT_PROFILE_MASK,&f1);
_glGetIntegerv(GL_CONTEXT_FLAGS,&f2);
printf("GLX Server ! : %s\n",glXQueryServerString(dsp ,0,GLX_ARB_create_context_profile));
printf("GLX Client ! : %s\n",glXGetClientString(dsp ,GLX_ARB_create_context_profile));
printf("Direct : %s\n",(direct == True ? "True" : "False"));
printf("Version (GetString) : %s\n",glGetString(GL_VERSION));
printf("Version (GetIntegerv) : %d.%d\n",glmaj,glmin);
printf("Profile/Flags : 0x%X.0x%X\n",f1,f2);
/*** OpenGL Context ARB ***/
XEvent event;
{
GLboolean cont = GL_TRUE;
while (cont) {
XNextEvent(dsp, &event);
}
}
return 0;
}
static void create_context_arb (void)
{
context = glXCreateContextAttribsARB (dsp , fb_choose_cfg[0], 0,True,gl_attr);
if(context == NULL)
printf ("glXCreateNewContext() : Failed !\n");
else
printf ("glXCreateNewContext() : Succeeded !\n");
if(!glXMakeCurrent(dsp,window,context))
printf("glXMakeCurrent() : Failed !\n");
else
printf("glXMakeCurrent() : Succeeded !\n");
}
static void create_context_default (void)
{
context = glXCreateContext(dsp , visual_info , None , True);
if(context == NULL)
printf ("glXCreateContext() : Failed !\n");
else
printf ("glXCreateContext() : Succeeded !\n");
if(!glXMakeCurrent(dsp,window,context))
printf ("glXMakeCurrent() : Failed !\n");
else
printf ("glXMakeCurrent() : Succeeded !\n");
}
static void create_context_new (void)
{
context = glXCreateNewContext(dsp , fb_choose_cfg[0],GLX_RGBA_TYPE,NULL,True);
if(context == NULL)
printf ("glXCreateNewContext() : Failed !\n");
else
printf ("glXCreateNewContext() : Succeeded !\n");
if(!glXMakeCurrent(dsp,window,context))
printf("glXMakeCurrent() : Failed !\n");
else
printf("glXMakeCurrent() : Succeeded !\n");
}
static void load_func (void)
{
glXCreateContextAttribsARB = glXGetProcAddress ((const GLubyte*) "glXCreateContextAttribsARB");
if(glXCreateContextAttribsARB == NULL)
printf("glXGetProcAddress() : Failed !\n");
else
printf("glXGetProcAddress() : Succeeded !\n");
}
یک پوشه درست کن مثلا به نام gltest .
حالا داخل پوشه ۲ تا پوشه دیگه درست کن به نام های bin و src .
این کد بالا رو در داخل پوشه src در فایل main.c ذخیره کن .
و این هم یه Makefile هست بره اینکه کدت رو راحت کامپایل کنی :
LIB_PATH =/lib64/
LIB_FILES =libGL.so libX11.so
DIR_SRC =src/
DIR_BIN =bin/
CC = gcc
PRINT = echo
CFLAGS = -Wall -c -std=c99
LFLAGS = -Wall
.PHONY: clean
.PHONY: glx
.PHONY: all
default: $(DIR_BIN)main
clean:
rm -rf bin/*.o
$(DIR_BIN)main.o : $(DIR_SRC)main.c
$(CC) $(CFLAGS) $(DIR_SRC)main.c -o $(DIR_BIN)main.o
$(DIR_BIN)main : $(DIR_BIN)main.o
$(CC) $(LFLAGS) -lGL -lX11 $(DIR_BIN)main.o -o $(DIR_BIN)main
این فایل بالا رو در پوشه gltest در فایل Makefile ذخیره کن .
و آخر هم ترمینال رو باز کن و به پوشه ی gltest برو و دستور make رو وارد کن . اونوقت برنامه کامپایل میشه و فایل اجرایی در پوشه ی bin درست میشه و میتونی اجراش کن .
البته اجباری نیست از Makefile استفاده کنی و میتونی خودت دستور ها رو در ترمینال بنویسی . ولی Makefile خیلی خوبه . باهاش کار کنی متوجه میشی که خیلی کارت رو راحت میکنه .