pswin.pooya
جمعه 15 مرداد 1389, 02:25 صبح
دوستانی که از قدیم با شیدر کار میکنن حتما شیدرهای اسمبلی رو به یاد دارن که بعد از اون شیدرهای High level Language اومدند مزیت شیدرهای اسمبلی توی سرعت کامپایلشون بود که عملا داخل OpenGL بعد از ویرایش 1.5 منسوخ شدن و تنها به صورت الحاقیهای سازنده ها به روز رسانی شدن. با معرفی OpenGL 4.1 (به تازگی توسط nvidia) یه الحاقی جدید معرفی شده که باعث میشه حتی لازم نباشه که شیدرها رو کامپایل کنید و کد باینری رو به کمک اون مستقیما بار کنید. این مساله میتونه مزایای زیادی مثل بالا رفتن سرعت لود بازی و یا حفظ کد اون داشته باشه و در کنار اون میتونه مسائلی مانند ناسازگاری رو هم پیش بیاره. خوبی این الحاقی اینه که از OpenGL 2.0 به بعد ساپورت میشه و این یعنی این الحاقی با تمام درایورهای سال 2004 به بعد کار میکنه و به نظر میاد برای بازیساز ها ایده آل باشه (مخصوصا اونهایی که شیدرهای زیادی داخل بازیشون دارن)
به هر حال اگر شیدرهای زیادی ندارین و یا نگران لو رفتن کد شیدرهاتون نیستید بهتره که برای حفظ سازگاری از همون GLSL استفاده بکنبد.
درایورهای جدید OpenGL (برای کارتهای nvidia):
http://developer.nvidia.com/object/opengl_driver.html
الحاقی GL_ARB_get_program_binary (http://www.opengl.org/registry/specs/ARB/get_program_binary.txt):
http://www.opengl.org/registry/specs/ARB/get_program_binary.txt
نحوه بارگذاری این شیدرها:
GLint formats = 0;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats)
GLenum *binaryFormats = new [formats];
glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, binaryFormats);
GLuint progId = glCreateProgram();
glProgramBinary(progId, binaryFormats, binary, len);
delete [] binary;
GLint success;
glGetProgramiv(progId, GL_LINK_STATUS, &success);
if (!success)
{
// Loading failed..}
.
شیوه ساخت شیدرهای باینری:
PFNGLGETPROGRAMIVPROC glGetProgramiv = 0;
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv");
typedef void * (WINAPI * PFNGLGETPROGRAMBINARYPROC) (unsigned int,
size_t, size_t *, GLenum *, void *);
PFNGLGETPROGRAMBINARYPROC glGetProgramBinary = 0;
glGetProgramBinary =
(PFNGLGETPROGRAMBINARYPROC)wglGetProcAddress("glGetProgramBinary");
if (glGetProgramBinary && glGetProgramiv)
{
static char *vertexShader=\
"void main()"
"{"
"gl_Position = gl_Vertex;"
"}";
static char *fragmentShader=\
"void main()"
"{"
"gl_FragColor=vec4(1.0, 0.4, 1.0, 1.0);"
"}";
int p = glCreateProgram();
int v = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v, 1, &vertexShader, 0);
glCompileShader(v);
glAttachShader(p,v);
int f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, &fragmentShader, 0);
glCompileShader(f);
glAttachShader(p,f);
glLinkProgram(p);
glUseProgram(p);
#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
#define GL_PROGRAM_BINARY_FORMATS 0x87FF
GLint formats = 0;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats);
GLint *binaryFormats = new GLint[formats];
glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, binaryFormats);
#define GL_PROGRAM_BINARY_LENGTH 0x8741
GLint len=0;
GLint progId = gpu->getGpuShaderData()->m_program_id;
glGetProgramiv(progId, GL_PROGRAM_BINARY_LENGTH, &len);
u8* binary = new u8[len];
glGetProgramBinary(progId, len, NULL, (GLenum*)binaryFormats, binary);
glUseProgram(0);
FILE* fp = fopen("shader.bin", "wb");
fwrite(binary, len, 1, fp);
fclose(fp);
delete [] binary;
// Don't forget the destruction of the GLSL shader...
// ...
به هر حال اگر شیدرهای زیادی ندارین و یا نگران لو رفتن کد شیدرهاتون نیستید بهتره که برای حفظ سازگاری از همون GLSL استفاده بکنبد.
درایورهای جدید OpenGL (برای کارتهای nvidia):
http://developer.nvidia.com/object/opengl_driver.html
الحاقی GL_ARB_get_program_binary (http://www.opengl.org/registry/specs/ARB/get_program_binary.txt):
http://www.opengl.org/registry/specs/ARB/get_program_binary.txt
نحوه بارگذاری این شیدرها:
GLint formats = 0;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats)
GLenum *binaryFormats = new [formats];
glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, binaryFormats);
GLuint progId = glCreateProgram();
glProgramBinary(progId, binaryFormats, binary, len);
delete [] binary;
GLint success;
glGetProgramiv(progId, GL_LINK_STATUS, &success);
if (!success)
{
// Loading failed..}
.
شیوه ساخت شیدرهای باینری:
PFNGLGETPROGRAMIVPROC glGetProgramiv = 0;
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv");
typedef void * (WINAPI * PFNGLGETPROGRAMBINARYPROC) (unsigned int,
size_t, size_t *, GLenum *, void *);
PFNGLGETPROGRAMBINARYPROC glGetProgramBinary = 0;
glGetProgramBinary =
(PFNGLGETPROGRAMBINARYPROC)wglGetProcAddress("glGetProgramBinary");
if (glGetProgramBinary && glGetProgramiv)
{
static char *vertexShader=\
"void main()"
"{"
"gl_Position = gl_Vertex;"
"}";
static char *fragmentShader=\
"void main()"
"{"
"gl_FragColor=vec4(1.0, 0.4, 1.0, 1.0);"
"}";
int p = glCreateProgram();
int v = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v, 1, &vertexShader, 0);
glCompileShader(v);
glAttachShader(p,v);
int f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, &fragmentShader, 0);
glCompileShader(f);
glAttachShader(p,f);
glLinkProgram(p);
glUseProgram(p);
#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
#define GL_PROGRAM_BINARY_FORMATS 0x87FF
GLint formats = 0;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats);
GLint *binaryFormats = new GLint[formats];
glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, binaryFormats);
#define GL_PROGRAM_BINARY_LENGTH 0x8741
GLint len=0;
GLint progId = gpu->getGpuShaderData()->m_program_id;
glGetProgramiv(progId, GL_PROGRAM_BINARY_LENGTH, &len);
u8* binary = new u8[len];
glGetProgramBinary(progId, len, NULL, (GLenum*)binaryFormats, binary);
glUseProgram(0);
FILE* fp = fopen("shader.bin", "wb");
fwrite(binary, len, 1, fp);
fclose(fp);
delete [] binary;
// Don't forget the destruction of the GLSL shader...
// ...