00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "glslShader.h"
00020
00021
00022 #ifndef GL_GLEXT_PROTOTYPES
00023 #define GL_GLEXT_PROTOTYPES
00024 #include <GL/glext.h>
00025 #endif
00026
00027
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <stdarg.h>
00031 #include <string.h>
00032
00033
00034
00035 const char* GLSL_ERR_NOT_VALID_PROGRAM = "Not a valid program object!\n";
00036 const char* GLSL_ERR_NO_PARAMETERS = "The program has no parameters or they are not in use!\n";
00037 const char* GLSL_ERR_CAN_NOT_CREATE = "Cannot create program object !!!\n Check if OpenGL subsystem is online.\n";
00038 const char* GLSL_ERR_WRONG_SHADER_TYPE = "Wrong shader type !\n";
00039 const char* GLSL_ERR_CANNOT_OPEN_FILE = "Can not open the shader file \"%s\" \n";
00040 const char* GLSL_ERR_NOT_LINKED = "Program object was not linked before!\n";
00041 const char* GLSL_ERR_NO_PARAMETER = "The parameter %s not exists or is not used\n";
00042 const char* GLSL_ERR_OUT_OF_MEMORY = "Out of Memory Error !!!\n";
00043 const char* GLSL_ERR_ONLY_BEFORE_LINK = "This can be used only before program was linked!\n";
00044
00045 #if 0
00046 #include <GL/glut.h>
00047
00048 void error_callback(GLSLprogram obj, void* param){
00049
00050 const char* LastError = glslGetLastErrorString();
00051
00052 if(LastError){
00053 printf("\n---------------------------------------------------\n");
00054 printf("%s\n", LastError);
00055 printf("---------------------------------------------------\n");
00056 printf("GLSL error, exiting...\n");
00057 exit(0);
00058 }
00059
00060 }
00061
00062 int main(int argc, char* argv[]){
00063
00064 glutInit(&argc, argv);
00065 glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH);
00066 glutInitWindowPosition(0, 0);
00067 glutInitWindowSize(100, 100);
00068 glutCreateWindow("GLSl Tester");
00069
00070
00071 GLSLprogram shader;
00072
00073 glslSetErrorCallback(error_callback, 0);
00074
00075 shader = glslCreateProgram();
00076 glslAttachShader(shader, "glsl/vDepthPNG.gl", GL_VERTEX_SHADER_ARB);
00077 glslLinkProgram(shader);
00078
00079
00080 return 0;
00081
00082 }
00083 #endif
00084
00085
00086
00087 void glslEmptyLastError();
00088 void glslFillLastError(const char* fmt, ...);
00089 void glslCheckError(GLSLprogram obj, GLSLbool internal);
00090 void glslGetParam(GLSLprogram obj, const char* name, GLSL_Param* param);
00091 char* glslScanAttributes(GLSLprogram obj, char* prog, GLSL_Attr **attr, GLSLint32* count);
00092
00093
00097 char ___glsl_last_error_string[4096];
00098
00102 GLSLbool ___glsl_has_last_error = GLSL_FALSE;
00103
00107 GLSLerrorCallback ___glsl_error_callback = 0;
00108
00109
00114 void* ___glsl_error_callback_param = 0;
00115
00116
00120 GLhandleARB _glsl_Program_Stack[GLSL_STACK_SIZE];
00121 GLSLint16 _glsl_Program_StackPos = 0;
00122
00123
00124
00125 void glslPush(){
00126 if (_glsl_Program_StackPos > GLSL_STACK_SIZE - 1){
00127 _glsl_Program_StackPos = GLSL_STACK_SIZE - 1;
00128 }
00129 _glsl_Program_Stack[_glsl_Program_StackPos] = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
00130 _glsl_Program_StackPos++;
00131 }
00132
00133 void glslPop(){
00134 if (_glsl_Program_StackPos < 1){
00135 return;
00136 }
00137 _glsl_Program_StackPos--;
00138 glUseProgramObjectARB(_glsl_Program_Stack[_glsl_Program_StackPos]);
00139 }
00140
00141 const char* glslGetLastErrorString(){
00142 return ___glsl_last_error_string;
00143 }
00144
00145
00155 void glslGetParam(GLSLprogram obj, const char* name, GLSL_Param* param){
00156
00157 if (obj == 0) return;
00158
00159
00160 if (obj->program == 0 || obj->is_valid == 0){
00161 glslFillLastError(GLSL_ERR_NOT_VALID_PROGRAM);
00162 glslCheckError(obj, 1);
00163 return;
00164 }
00165
00166
00167 if (obj->params == 0){
00168 glslFillLastError(GLSL_ERR_NO_PARAMETERS);
00169 glslCheckError(obj, 1);
00170 return;
00171 }
00172
00173 param->location = glGetUniformLocationARB(obj->program, (const GLcharARB*)name);
00174
00175 }
00176
00177
00178 GLSLprogram glslCreateProgram(){
00179
00180 GLSLprogram prog = 0;
00181
00182 prog = (GLSLprogram)malloc(sizeof(GLSL_Shader));
00183 if (prog == 0) return 0;
00184
00185
00186 prog->is_valid = 0;
00187
00188
00189 prog->params = 0;
00190 prog->param_count = 0;
00191
00192
00193 prog->program = glCreateProgramObjectARB();
00194
00195 if (prog->program == 0){
00196 glslFillLastError(GLSL_ERR_CAN_NOT_CREATE);
00197 glslCheckError(prog, 1);
00198 }else{
00199 glslEmptyLastError();
00200 }
00201
00202 return prog;
00203
00204 }
00205
00206
00207 void glslAttachShaderFromMemory(GLSLprogram obj, const char* prog, size_t size, GLSL_ShaderType shaderType)
00208 {
00209 if (obj == 0) return;
00210
00211
00212 if (shaderType != GLSL_VERTEX && shaderType != GLSL_FRAGMENT){
00213 glslFillLastError(GLSL_ERR_WRONG_SHADER_TYPE);
00214 glslCheckError(obj, 1);
00215 return;
00216 }
00217
00218 if (obj->program == 0){
00219 glslFillLastError(GLSL_ERR_NOT_VALID_PROGRAM);
00220 glslCheckError(obj, 1);
00221 return;
00222 }
00223
00224 #if 0
00225
00226 GLSL_Attr* attr = 0;
00227 int count = 0;
00228 char* ndata = glslScanAttributes(obj, prog, &attr, &count);
00229 #endif
00230
00231
00232 GLenum shType = shaderType == GLSL_VERTEX ? GL_VERTEX_SHADER_ARB : GL_FRAGMENT_SHADER_ARB;
00233
00234
00235 GLhandleARB shader = glCreateShaderObjectARB(shType);
00236 glShaderSourceARB(shader, 1, (const GLcharARB**)&prog, (const GLint*)&size);
00237 glCompileShaderARB(shader);
00238 glAttachObjectARB(obj->program, shader);
00239 glDeleteObjectARB(shader);
00240
00241 #if 0
00242
00243 for (int i=0; i < count; i++){
00244 glBindAttribLocationARB(obj->program, attr[i].index, attr[i].name);
00245 }
00246 free(ndata);
00247 #endif
00248
00249 glslCheckError(obj, 0);
00250
00251 }
00252
00253
00254 void glslAttachShader(GLSLprogram obj, const char* filename, GLSL_ShaderType shaderType){
00255
00256 if (obj == 0) return;
00257
00258 char* data = 0;
00259 size_t size = 0;
00260 FILE* file = 0;
00261
00262
00263 if (shaderType != GLSL_VERTEX && shaderType != GLSL_FRAGMENT){
00264 glslFillLastError(GLSL_ERR_WRONG_SHADER_TYPE);
00265 glslCheckError(obj, 1);
00266 return;
00267 }
00268
00269 if (obj->program == 0){
00270 glslFillLastError(GLSL_ERR_NOT_VALID_PROGRAM);
00271 glslCheckError(obj, 1);
00272 return;
00273 }
00274
00275
00276
00277 file = fopen(filename,"rb");
00278 if(!file) {
00279 glslFillLastError(GLSL_ERR_CANNOT_OPEN_FILE, filename);
00280 glslCheckError(obj, 1);
00281 return;
00282 }
00283
00284
00285 fseek(file,0,SEEK_END);
00286 size = ftell(file);
00287 data = (char*)malloc(sizeof(char)*(size + 1));
00288 memset(data, 0, sizeof(char)*(size + 1));
00289 fseek(file,0,SEEK_SET);
00290 fread(data,1,size,file);
00291 fclose(file);
00292
00293
00294 glslAttachShaderFromMemory(obj, data, size, shaderType);
00295
00296 free(data);
00297
00298 }
00299
00300
00301 void glslAttachVertexShader(GLSLprogram obj, const char* filename)
00302 {
00303 glslAttachShader(obj, filename, GLSL_VERTEX);
00304 }
00305
00306
00307 void glslAttachFragmentShader(GLSLprogram obj, const char* filename)
00308 {
00309 glslAttachShader(obj, filename, GLSL_FRAGMENT);
00310 }
00311
00312
00313 void glslAttachVertexShaderFromMemory(GLSLprogram obj, const char* prog, size_t size)
00314 {
00315 glslAttachShaderFromMemory(obj, prog, size, GLSL_VERTEX);
00316 }
00317
00318
00319 void glslAttachFragmentShaderFromMemory(GLSLprogram obj, const char* prog, size_t size)
00320 {
00321 glslAttachShaderFromMemory(obj, prog, size, GLSL_FRAGMENT);
00322 }
00323
00324
00325
00326 void glslBindAttribute(GLSLprogram obj, GLSLint32 attrIndex, char* name){
00327
00328 if (obj == 0)return;
00329
00330 glBindAttribLocationARB(obj->program, attrIndex, name);
00331
00332
00333 if (obj->is_valid){
00334 glslLinkProgram(obj);
00335 }
00336 }
00337
00338
00363 char* glslScanAttributes(GLSLprogram obj, char* prog, GLSL_Attr **attr, GLSLint32* count){
00364
00365 if (attr == 0 || count == 0){
00366 return prog;
00367 }
00368
00369
00370 char* new_prog = 0;
00371 new_prog = (char*)malloc(strlen(prog)*sizeof(char));
00372 if (new_prog == 0){
00373 glslFillLastError(GLSL_ERR_OUT_OF_MEMORY);
00374 glslCheckError(obj, 1);
00375 return prog;
00376 }
00377 memset(new_prog, 0, sizeof(char)*strlen(prog));
00378
00379
00380 GLSL_Attr attrTemp[64];
00381 int attrCount = 0;
00382
00383
00384 char* source = prog;
00385 char* dest = new_prog;
00386 while (1){
00387
00388 char* at = strstr(source, "attribute ");
00389
00390
00391 if (at == 0){
00392 static int i = 0;
00393 i++;
00394 fprintf(stderr, "%i - %i\n", i, source - prog);
00395
00396 strcpy(dest, source);
00397 break;
00398 }
00399
00400
00401 int index = -1;
00402 int space_count = 0;
00403 char name[GLSL_LONGEST_NAME+1];
00404 int name_index = 0;
00405 memset(name, 0, sizeof(char) * (GLSL_LONGEST_NAME+1));
00406 char* s = at;
00407 while (*s != ';' && *s != '\0'){
00408
00409 if (*s == ':'){
00410 s++;
00411 while (*s == ' ' && *s != '\0')s++;
00412 if (*s == '\0')break;
00413
00414
00415 if (*(s++) != 'A') break;
00416 if (*(s++) != 'T') break;
00417 if (*(s++) != 'T') break;
00418 if (*(s++) != 'R') break;
00419
00420
00421
00422 char buffer[5];
00423 memset(buffer, 0, 5*sizeof(char));
00424 int cb = 0;
00425 while (*s != '\0' && *s != ' ' && *s != ';' && cb < 5){
00426 buffer[cb] = *s;
00427 s++;
00428 cb++;
00429 }
00430
00431
00432 if (strlen(buffer) == 0) break;
00433
00434
00435 index = atoi(buffer);
00436
00437
00438
00439 }else{
00440
00441
00442
00443 if (*s == ' ' || *s == ';' || *s == ':')space_count++;
00444 if (space_count >= 2){
00445
00446 if (space_count == 3 && *s != ' ' && *s != ':' && *s != ';'){
00447 name[name_index++] = *s;
00448 }
00449 }
00450 }
00451
00452
00453 *(dest++) = *s;
00454
00455
00456 if (*s != ';') s++;
00457
00458 }
00459
00460
00461
00462
00463
00464 if (name_index == 0){
00465 strcpy(dest, source);
00466 break;
00467 }
00468
00469
00470 attrTemp[attrCount].index = index;
00471 strcpy(attrTemp[attrCount].name, name);
00472 attrCount++;
00473
00474
00475
00476 source = s;
00477
00478 }
00479
00480
00481 if (attrCount > 0){
00482 *attr = (GLSL_Attr*)malloc(sizeof(GLSL_Attr) * attrCount);
00483 if (*attr != 0){
00484 *count = attrCount;
00485 int i = 0;
00486 for (i=0; i < attrCount; i++){
00487 ((*attr)[i]).index = attrTemp[i].index;
00488 strcpy(((*attr)[i]).name, attrTemp[i].name);
00489 }
00490 }
00491 }
00492
00493 return new_prog;
00494 }
00495
00496
00497
00498 void glslLinkProgram(GLSLprogram obj){
00499
00500 if (obj == 0) return;
00501
00502
00503 if (obj->program == 0){
00504 glslFillLastError(GLSL_ERR_NOT_VALID_PROGRAM);
00505 glslCheckError(obj, 1);
00506 return;
00507 }
00508
00509
00510 glLinkProgramARB(obj->program);
00511 GLint linked;
00512 glGetObjectParameterivARB(obj->program, GL_OBJECT_LINK_STATUS_ARB, &linked);
00513 if(!linked) {
00514 glslCheckError(obj, 0);
00515 return;
00516 }
00517
00518 obj->is_valid = 1;
00519 glslEmptyLastError();
00520
00521
00522
00523 GLint count = 0;
00524 glGetObjectParameterivARB(obj->program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count);
00525
00526
00527 if (count > 0){
00528 obj->param_count = count;
00529 obj->params = (GLSL_Param*)malloc(count* sizeof(GLSL_Param));
00530 memset(obj->params, 0, count* sizeof(GLSL_Param));
00531
00532 GLuint i = 0;
00533 for (i=0; i < (GLuint)count; i++){
00534 GLsizei length = 0;
00535 GLint size = 0;
00536 GLenum type;
00537 GLcharARB name[GLSL_LONGEST_NAME];
00538 memset(name, 0, GLSL_LONGEST_NAME*sizeof(GLcharARB));
00539
00540 glGetActiveUniformARB(obj->program,i, GLSL_LONGEST_NAME, &length, &size, &type, &(name[0]));
00541
00542
00543 if (length < GLSL_LONGEST_NAME)
00544 memcpy(obj->params[i].name, name, sizeof(char)*length);
00545 else
00546 memcpy(obj->params[i].name, name, sizeof(char)*GLSL_LONGEST_NAME);
00547
00548
00549 obj->params[i].length = size;
00550 obj->params[i].type = type;
00551 obj->params[i].location = glGetUniformLocationARB(obj->program, name);
00552 }
00553 }
00554
00555 }
00556
00557
00558
00559 void glslDeleteProgram(GLSLprogram obj){
00560 if (obj == 0) return;
00561 if (obj->program) glDeleteObjectARB(obj->program);
00562
00563 if (obj->params != 0)free(obj->params);
00564 free(obj);
00565 }
00566
00567
00571 void glslEmptyLastError(){
00572 memset(___glsl_last_error_string, 0, sizeof(___glsl_last_error_string));
00573 ___glsl_has_last_error = 0;
00574 }
00575
00576
00580 void glslFillLastError(const char* fmt, ...){
00581
00582 char buf[4096];
00583
00584 va_list(ap);
00585 va_start(ap, fmt);
00586 vsprintf(buf, fmt, ap);
00587 va_end(ap);
00588
00589 strcpy(___glsl_last_error_string, buf);
00590
00591 ___glsl_has_last_error = 1;
00592 }
00593
00604 void glslCheckError(GLSLprogram obj, GLSLbool internal){
00605
00606 GLSLbool occurs = internal;
00607
00608 if (internal == 0){
00609 size_t length = 0;
00610 static char error[4096];
00611 glGetInfoLogARB(obj->program, 4096, (GLsizei*)&length, error);
00612
00613 glslEmptyLastError();
00614
00615 if (length > 0){
00616 strcpy(___glsl_last_error_string, error);
00617 ___glsl_has_last_error = 1;
00618
00619 if (strstr(error, "warning:") == 0){
00620 occurs = 1;
00621 }
00622 }
00623 }
00624
00625 if (___glsl_error_callback && occurs){
00626 ___glsl_error_callback(obj, ___glsl_error_callback_param);
00627 }
00628
00629
00630 }
00631
00632
00633
00634 GLSLbool glslHasError(){
00635 return ___glsl_has_last_error;
00636 }
00637
00638
00639
00640 void glslSetErrorCallback(GLSLerrorCallback pCallback, void* callbackParam){
00641 ___glsl_error_callback = pCallback;
00642 ___glsl_error_callback_param = callbackParam;
00643 }
00644
00645
00646
00647 void glslSetParameterf(GLSLprogram obj, const char* name, GLSLint8 size, const GLSLfloat32* value){
00648
00649 if (obj == 0) return;
00650 if (obj->is_valid == 0){
00651 glslFillLastError(GLSL_ERR_NOT_LINKED);
00652 glslCheckError(obj, 1);
00653 return;
00654 }
00655
00656 GLSL_Param param;
00657 glslGetParam(obj, name, ¶m);
00658
00659 if (param.location != -1){
00660 if(size == 1) glUniform1fARB(param.location, value[0]);
00661 else if(size == 2) glUniform2fARB(param.location, value[0], value[1]);
00662 else if(size == 3) glUniform3fARB(param.location, value[0], value[1], value[2]);
00663 else if(size == 4) glUniform4fARB(param.location, value[0], value[1], value[2], value[3]);
00664 glslCheckError(obj, 0);
00665 }else{
00666 glslFillLastError(GLSL_ERR_NO_PARAMETER, name);
00667 glslCheckError(obj, 1);
00668 }
00669
00670 }
00671
00672
00673 void glslSetParameter1f(GLSLprogram obj, const char* name, const GLSLfloat32 value){
00674 glslSetParameterf(obj, name, 1, &value);
00675 }
00676
00677
00678
00679 void glslSetParameter2f(GLSLprogram obj, const char* name, const GLSLfloat32* value){
00680 glslSetParameterf(obj, name, 2, value);
00681 }
00682
00683
00684 void glslSetParameter3f(GLSLprogram obj, const char* name, const GLSLfloat32* value){
00685 glslSetParameterf(obj, name, 3, value);
00686 }
00687
00688
00689 void glslSetParameter4f(GLSLprogram obj, const char* name, const GLSLfloat32* value){
00690 glslSetParameterf(obj, name, 4, value);
00691 }
00692
00693
00694 void glslSetParameteri(GLSLprogram obj, const char* name, GLSLint8 size, const GLSLint32* value){
00695
00696 if (obj == 0) return;
00697 if (obj->is_valid == 0){
00698 glslFillLastError(GLSL_ERR_NOT_LINKED);
00699 glslCheckError(obj, 1);
00700 return;
00701 }
00702
00703 GLSL_Param param;
00704 glslGetParam(obj, name, ¶m);
00705
00706 if (param.location != -1){
00707 if(size == 1) glUniform1iARB(param.location, value[0]);
00708 else if(size == 2) glUniform2iARB(param.location, value[0], value[1]);
00709 else if(size == 3) glUniform3iARB(param.location, value[0], value[1], value[2]);
00710 else if(size == 4) glUniform4iARB(param.location, value[0], value[1], value[2], value[3]);
00711 glslCheckError(obj, 0);
00712 }else{
00713 glslFillLastError(GLSL_ERR_NO_PARAMETER, name);
00714 glslCheckError(obj, 1);
00715 }
00716 }
00717
00718
00719 void glslSetParameter1i(GLSLprogram obj, const char* name, const GLSLint32 value){
00720 glslSetParameteri(obj, name, 1, &value);
00721 }
00722
00723
00724
00725 void glslSetParameter2i(GLSLprogram obj, const char* name, const GLSLint32* value){
00726 glslSetParameteri(obj, name, 2, value);
00727 }
00728
00729
00730 void glslSetParameter3i(GLSLprogram obj, const char* name, const GLSLint32* value){
00731 glslSetParameteri(obj, name, 3, value);
00732 }
00733
00734
00735 void glslSetParameter4i(GLSLprogram obj, const char* name, const GLSLint32* value){
00736 glslSetParameteri(obj, name, 4, value);
00737 }
00738
00739
00740
00741 void glslSetMatrixParameter(GLSLprogram obj, const char* name, GLSLint8 size, const GLSLfloat32* mat, GLSLbool trans){
00742
00743 if (obj == 0) return;
00744 if (obj->is_valid == 0){
00745 glslFillLastError(GLSL_ERR_NOT_LINKED);
00746 glslCheckError(obj, 1);
00747 return;
00748 }
00749
00750 GLSL_Param param;
00751 glslGetParam(obj, name, ¶m);
00752
00753 if (param.location != -1){
00754 if(size == 4) glUniformMatrix2fvARB(param.location,1,trans,mat);
00755 else if(size == 9) glUniformMatrix3fvARB(param.location,1,trans,mat);
00756 else if(size == 16)glUniformMatrix4fvARB(param.location,1,trans,mat);
00757 glslCheckError(obj, 0);
00758 }else{
00759 glslFillLastError(GLSL_ERR_NO_PARAMETER, name);
00760 glslCheckError(obj, 1);
00761 }
00762
00763 }
00764
00765
00766
00767 void glslSetMatrixParameter4(GLSLprogram obj, const char* name, const GLSLfloat32* mat, GLSLbool trans){
00768 glslSetMatrixParameter(obj, name, 4, mat, trans);
00769 }
00770
00771
00772 void glslSetMatrixParameter9(GLSLprogram obj, const char* name, const GLSLfloat32* mat, GLSLbool trans){
00773 glslSetMatrixParameter(obj, name, 9, mat, trans);
00774 }
00775
00776
00777
00778 void glslSetMatrixParameter16(GLSLprogram obj, const char* name, const GLSLfloat32* mat, GLSLbool trans){
00779 glslSetMatrixParameter(obj, name, 16, mat, trans);
00780 }
00781
00782
00783
00784 void glslSetTexture(GLSLprogram obj, const char* name, GLSLuint32 texture_unit){
00785
00786 if (obj == 0) return;
00787 if (obj->is_valid == 0 || obj->program == 0){
00788 glslFillLastError(GLSL_ERR_NOT_LINKED);
00789 glslCheckError(obj, 1);
00790 return;
00791 }
00792
00793 GLSL_Param param;
00794 glslGetParam(obj, name, ¶m);
00795
00796 if (param.location != -1){
00797 glUniform1iARB(param.location, (GLuint)texture_unit);
00798 glslCheckError(obj, 0);
00799 }else{
00800 glslFillLastError(GLSL_ERR_NO_PARAMETER, name);
00801 glslCheckError(obj, 1);
00802 }
00803 }
00804
00805
00806
00807
00808 void glslEnableProgram(GLSLprogram obj){
00809 if (obj == 0) return;
00810 if (obj->program && obj->is_valid) glUseProgramObjectARB(obj->program);
00811 }
00812
00813
00814
00815 void glslDisableProgram(GLSLprogram obj){
00816 if (obj == 0) return;
00817 if (obj->program && obj->is_valid) glUseProgramObjectARB(0);
00818 }
00819
00820
00821 void glslDisable(){
00822 glUseProgramObjectARB(0);
00823 }
00824
00825
00826 int glslGetUniformParameterCount(GLSLprogram obj){
00827 if (obj == 0) return 0;
00828 return obj->param_count;
00829 }
00830
00831
00832 GLint glslGetUniformLocation(GLuint active_program, const char *name)
00833 {
00834 int loc = glGetUniformLocation(active_program, (const GLcharARB*)name);
00835 return loc;
00836 }
00837
00838 #if 0
00839
00840 GLint glslGetUniformLocation(GLSLprogram obj, const char *name)
00841 {
00842 return glslGetUniformLocation(obj->program, name);
00843 }
00844 #endif
00845
00846
00847 void glslCreateProgram_Quick(GLSLprogram *new_program, char *vshader_filename, char *fshader_filename)
00848 {
00849 *new_program = glslCreateProgram();
00850 if (vshader_filename)
00851 glslAttachVertexShader(*new_program, vshader_filename);
00852
00853 if (fshader_filename)
00854 glslAttachFragmentShader(*new_program, fshader_filename);
00855
00856 glslLinkProgram(*new_program);
00857 }
00858