rendered paste body#ifndef _SHADER_H_#define _SHADER_H_//Shader Platform Definitions.#define NONE 0#define GLSL 1#define CG 2#define HLSL 3#define IMPL GLSL#if (IMPL == NONE)#define USE_NONE#elif (IMPL == GLSL)#define USE_GLSL#else#error Unsupported in Allegro 5.1#endif //(IMPL == GLSL)#ifdef USE_NONE#define IMPL_ID "none"#define PLATFORM #endif //USE_NONE#ifdef USE_GLSL#include "allegro5/allegro_opengl.h"#include "allegro5/allegro_shader_glsl.h"#define IMPL_ID "glsl"#define PLATFORM ALLEGRO_SHADER_GLSL#endif //USE_GLSL//Shader Definitions.#define SHADER_PIXEL 0#define SHADER_VERTEX 1#define SHADER_FRAGMENT SHADER_PIXEL#define SHADER_TYPES 2#define SHADER_PARAM_USE_SRC_MATRIX "use_tex_matrix"#define SHADER_PARAM_SRC_MATRIX "tex_matrix"#define SHADER_PARAM_USE_SRC "use_tex"#define SHADER_PARAM_SRC "tex"#define SHADER_PARAM_DEST "dest"#define SHADER_PARAM_AUX "aux"#define SHADER_PARAM_VARYINGCOLOR "varying_color"#define SHADER_PARAM_VARYINGCOORD "varying_texcoord"#define SHADER_PARAM_TIME "time"#ifdef USE_NONEtypedef void *shaderhandle;#elsetypedef ALLEGRO_SHADER *shaderhandle;#endif //USE_NONEtypedef struct _shader { shaderhandle shaders;} shader;//Initialize Shader System.int init_shaders();//Destroy Shader System.void quit_shaders();//Destroy a Shadervoid destroy_shader(shader *shade);//Create an Identity Shadershader *identity_shader();//Create a Shadershader *create_shader(char *shadername);char shader_type_id[SHADER_TYPES][MAXSTR]={"pixel","vertex"};char shader_suffix[MAXSTR] = {".shader"};//Needed if not Fixed Function.static shader *identity = NULL;#ifndef USE_NONEchar identityshadercode[SHADER_TYPES][MAXSTR]={ //Pixel "uniform bool "SHADER_PARAM_USE_SRC";\n" "uniform sampler2D "SHADER_PARAM_SRC";\n" "uniform bool "SHADER_PARAM_USE_SRC_MATRIX";\n" "uniform mat4 "SHADER_PARAM_SRC_MATRIX";\n" "varying vec2 "SHADER_PARAM_VARYINGCOORD";\n" "varying vec4 "SHADER_PARAM_VARYINGCOLOR";\n" "void main(){\n" " vec4 tmp = "SHADER_PARAM_VARYINGCOLOR";\n" " vec4 coord = vec4("SHADER_PARAM_VARYINGCOORD", 0.0, 1.0);\n" " if ("SHADER_PARAM_USE_SRC") {\n" " vec4 sample = texture2D("SHADER_PARAM_SRC", coord.st);\n" " tmp *= sample;\n" " } else if ("SHADER_PARAM_USE_SRC_MATRIX") {\n" " vec4 sample;\n" " coord = coord * "SHADER_PARAM_SRC_MATRIX";\n" " sample = texture2D("SHADER_PARAM_SRC", coord.st);\n" " tmp *= sample;\n" " }\n" " gl_FragColor = tmp;\n" "}\n" , //Vertex "attribute vec4 pos;\n" "attribute vec4 color;\n" "attribute vec2 texcoord;\n" "uniform mat4 projview_matrix;\n" "varying vec4 "SHADER_PARAM_VARYINGCOLOR";\n" "varying vec2 "SHADER_PARAM_VARYINGCOORD";\n" "void main(){\n" ""SHADER_PARAM_VARYINGCOLOR" = color;\n" ""SHADER_PARAM_VARYINGCOORD" = texcoord;\n"#ifndef LINUX "gl_PointSize = 1.0;\n"#endif //LINUX "gl_Position = projview_matrix * pos;\n" "}\n" };#endif //USE_NONE//Initialize Shader System.int init_shaders(){ log_printf("Initializing Shader System"); #ifdef USE_GLSL al_set_new_display_flags(ALLEGRO_USE_PROGRAMMABLE_PIPELINE | ALLEGRO_OPENGL); #endif //USE_GLSL return 0;}//Destroy Shader System.void quit_shaders(){ if(identity) { destroy_shader(identity); identity=NULL; } log_printf("Uninitializing Shader System");}//Destroy a Shadervoid destroy_shader(shader *shade){ if(shade) { if(shade->shaders) { #ifndef USE_NONE al_destroy_shader(shade->shaders); shade->shaders=NULL; #endif //USE_NONE } free(shade); shade=NULL; log_printf("Destroyed Shader."); }}#ifndef USE_NONE//Compile a Shader from a String.static int shaderhandle_compile_string(shaderhandle shade, char *string, int type){#ifndef USE_NONE ALLEGRO_SHADER_TYPE atype; if(type == SHADER_PIXEL) { atype = ALLEGRO_PIXEL_SHADER; } else if(type == SHADER_VERTEX) { atype = ALLEGRO_VERTEX_SHADER; } else { return -1; } if(shade == NULL) { return -1; } if (!al_attach_shader_source(shade, atype, string)) { log_printf( "Error Compiling Shader of Type: %s %s\n", shader_type_id[type], al_get_shader_log(shade)); return -1; }#endif return 0;}//Compile a Shader from a File.static int shaderhandle_compile_file(shaderhandle shade, char *shader_path, int type){ char *str = get_file_contents(shader_path, NULL); int retval = -1; if(str) { retval = shaderhandle_compile_string(shade, str, type); free(str); str=NULL; } return retval;}#endif //USE_NONE//Create a Shader.shader *create_shader(char *shadername) { shader *s = malloc(sizeof(shader)); if(s) { int loaded; s->shaders = NULL; loaded = 0; #ifndef USE_NONE s->shaders = al_create_shader(PLATFORM); if(s->shaders) { char shaderfilename[MAXSTR]; int t; for(t=0;t<SHADER_TYPES;++t) { int retval=0; *shaderfilename=0; sprintf(shaderfilename,"%s%c%s%c%s%c%s%c%s%s",DATADIR,PATHSEP,"Shaders",PATHSEP,shadername,PATHSEP,shader_type_id[t],'_',IMPL_ID,".shader"); if(file_exists(shaderfilename)) retval = shaderhandle_compile_file(s->shaders, shaderfilename, t); else retval = shaderhandle_compile_string(s->shaders, identityshadercode[t], t); if(retval == -1) { log_printf("Unable to Load Shader: %s", shadername); } else { ++loaded; } } if (!loaded || !al_link_shader(s->shaders)) { log_printf("Error Linking Shader: %s %s", shadername, al_get_shader_log(s->shaders)); destroy_shader(s); s=NULL; } else { #ifdef USE_GLSL al_set_opengl_program_object(screen, al_get_opengl_program_object(s->shaders)); #endif //USE_GLSL log_printf("Successfully Loaded Shader: %s", shadername); } } #endif //USE_NONE } return s;}//Create an Identity Shadershader *identity_shader(){ if(identity) return identity; identity = create_shader("identity"); return identity;}//Source file for miscellaneous functions and utilities.//File Exists.int file_exists(char *file){ FILE *rfile = NULL; rfile = fopen(file, "rb"); if(rfile) { fclose(rfile); rfile = NULL; return 1; } return 0;}//Get File Length.static long get_file_length(FILE *file){ long fcur,flength; fcur=ftell(file); fseek(file,0,SEEK_END ); flength = ftell(file); fseek (file,fcur,SEEK_SET ); return flength;}//Get File Contents.char *get_file_contents(char *file, long *length){ FILE *rfile = NULL; long flength = 0; char *array = NULL; if(file) rfile = fopen(file, "rb"); if(rfile) { flength = get_file_length(rfile); array = malloc(sizeof(char)*(flength+1)); if(array) { fread(array, sizeof(char), flength, rfile); array[flength]=0; } fclose(rfile); rfile=NULL; } if(length) *length = flength; return array;}#ifdef USE_NONE#define set_shader_params(...)#define unset_shader_params(...)//Sets Current Shader for Draw.void set_shader(shader *s){ }//Unsets Shader.void unset_shader(){ }#elsestatic shader *current = NULL;static void set_shader_params(ALLEGRO_BITMAP *src, ALLEGRO_BITMAP *dest, ALLEGRO_BITMAP *aux){ if(current == NULL) current = identity_shader(); if(current) { if(src) { al_set_shader_bool(current->shaders, SHADER_PARAM_USE_SRC, true); al_set_shader_sampler(current->shaders, SHADER_PARAM_SRC, src, 0); } if(!dest) dest = al_get_target_bitmap(); if(dest) al_set_shader_sampler(current->shaders, SHADER_PARAM_DEST, dest, 1); if(aux) al_set_shader_sampler(current->shaders, SHADER_PARAM_AUX, aux, 2); al_use_shader(current->shaders, true); }}static void unset_shader_params(){ if(current == NULL) current = identity_shader(); if(current) { al_use_shader(current->shaders, false); }}//Sets Current Shader for Draw.void set_shader(shader *s) { if(s) current = s;}//Unsets Shader.void unset_shader(){ current = NULL;}#endif //USE_NONE//Loads a ALLEGRO_BITMAPALLEGRO_BITMAP *load_bitmap_ex(char *file, ALLEGRO_COLOR *pal){ ALLEGRO_BITMAP *lbmp=NULL; lbmp=al_load_bitmap(file); if(lbmp) { // Set magenta to transparent al_convert_mask_to_alpha(lbmp, al_map_rgb(255, 0, 255)); } return lbmp;}//Blits a Bitmap to Screenvoid blit(ALLEGRO_BITMAP *src, float sx, float sy, float dx, float dy, float sw, float sh) { set_shader_params(src, NULL, NULL); al_draw_bitmap_region(src, sx, sy, sw, sh, dx, dy, 0); unset_shader_params();}//Rotates a Bitmap and Blits to Screenvoid rotated_blit(ALLEGRO_BITMAP *src, float sx, float sy, float dx, float dy, float sw, float sh, float angle) { ALLEGRO_TRANSFORM old, T; al_copy_transform(&old, al_get_current_transform()); al_build_transform(&T,dx,dy,1.0f,1.0f,angle); al_use_transform(&T); set_shader_params(src, NULL, NULL); blit(src,sx,sy,-0.5f*sw,-0.5f*sh,sw,sh); unset_shader_params(); al_use_transform(&old);}//Stretches a Bitmap and Draws to Screenvoid stretch_blit(ALLEGRO_BITMAP *src, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh) { set_shader_params(src, NULL, NULL); al_draw_scaled_bitmap(src, sx, sy, sw, sh, dx, dy, dw, dh, 0); unset_shader_params();}