#include #include #include "SDL.h" #define GL_GLEXT_PROTOTYPES #include #include #include "rainbow.h" static PFNGLGETOBJECTPARAMETERIVARBPROC eglGetObjectParameterivARB =NULL; static PFNGLGETINFOLOGARBPROC eglGetInfoLogARB =NULL; static PFNGLCREATESHADEROBJECTARBPROC eglCreateShaderObjectARB =NULL; static PFNGLSHADERSOURCEARBPROC eglShaderSourceARB =NULL; static PFNGLCOMPILESHADERARBPROC eglCompileShaderARB =NULL; static PFNGLCREATEPROGRAMOBJECTARBPROC eglCreateProgramObjectARB =NULL; static PFNGLATTACHOBJECTARBPROC eglAttachObjectARB =NULL; static PFNGLLINKPROGRAMARBPROC eglLinkProgramARB =NULL; static PFNGLUNIFORM1IARBPROC eglUniform1iARB =NULL; static PFNGLGETUNIFORMLOCATIONARBPROC eglGetUniformLocationARB =NULL; static PFNGLUSEPROGRAMOBJECTARBPROC eglUseProgramObjectARB =NULL; static void vr_glext_glsl_init_exts() { static bool init=false; if (init) return; eglGetObjectParameterivARB=(PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB"); eglGetInfoLogARB=(PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB"); eglCreateShaderObjectARB=(PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB"); eglShaderSourceARB=(PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB"); eglCompileShaderARB=(PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB"); eglCreateProgramObjectARB=(PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB"); eglAttachObjectARB=(PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB"); eglLinkProgramARB=(PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB"); eglUniform1iARB=(PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); eglGetUniformLocationARB=(PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); eglUseProgramObjectARB=(PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB"); } static void vr_glext_glsl_dump_log(GLhandleARB p,const GLcharARB* shader) { vr_glext_glsl_init_exts(); GLint log_size; eglGetObjectParameterivARB(p, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_size); if (log_size>1) { GLcharARB* s=(GLcharARB*)malloc((log_size+1)*sizeof(GLcharARB)); eglGetInfoLogARB(p,log_size,NULL,s); printf("============================================================\n"); printf("Faulty ARB program. Log (%d bytes) : \n%s\n",log_size,s); free(s); printf("Faulty ARB program : \n"); int lc=0; printf("\n%4d: ",++lc); for(int i=0;i<(int)strlen(shader);i++) { if (shader[i]=='\n') printf("\n%4d: ",++lc); else printf("%c",shader[i]); } printf("\n"); printf("============================================================\n"); } } bool vr_glext_glsl_create_program(const GLcharARB* vshader,const GLcharARB* fshader,GLhandleARB* res) { vr_glext_glsl_init_exts(); GLint ok; GLhandleARB vs=eglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); GLhandleARB fs=eglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); eglShaderSourceARB(vs, 1, &vshader,NULL); eglShaderSourceARB(fs, 1, &fshader,NULL); eglCompileShaderARB(vs); vr_glext_glsl_dump_log(vs,vshader); eglGetObjectParameterivARB(vs,GL_OBJECT_COMPILE_STATUS_ARB,&ok); if (!ok) { printf("compiling vertex shader\n"); return false; } eglCompileShaderARB(fs); vr_glext_glsl_dump_log(fs,fshader); eglGetObjectParameterivARB(fs,GL_OBJECT_COMPILE_STATUS_ARB,&ok); if (!ok) { printf("compiling fragment shader\n"); return false; } GLhandleARB p = eglCreateProgramObjectARB(); eglAttachObjectARB(p,vs); eglAttachObjectARB(p,fs); eglLinkProgramARB(p); vr_glext_glsl_dump_log(p,"(Linking Stage)"); eglGetObjectParameterivARB(p,GL_OBJECT_LINK_STATUS_ARB,&ok); if (!ok) { printf("linking program\n"); return false; } *res=p; return true; } char vshader[] = "void main()" "{" " gl_TexCoord[0] = gl_MultiTexCoord0;" " gl_Position = ftransform();" "}"; char fshader_mandelbrot[] = "uniform sampler1D transfer_function; \n" "void main () \n" "{ \n" " vec2 c = gl_TexCoord[0].xy; \n" " vec2 z = c; \n" " float i = 0.0; \n" " \n" " while( (dot(z,z) < 4.0) && (i<32.0) ) \n" " { \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " i+= 1.0; \n" " } \n" " gl_FragColor = texture1D(transfer_function, (i / 32.0) ); \n" "} \n" ; char fshader_julia[] = "uniform sampler1D transfer_function; \n" "void main () \n" "{ \n" " vec2 c = vec2(-0.7, 0.27015); \n" " vec2 z = gl_TexCoord[0].xy; \n" " vec2 oldz; \n" " float i = 0.0; \n" " \n" " do \n" " { \n" " oldz = z; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " i+= 16.0; \n" " } \n" " while( (i<256.0) && (dot(z,z) < 4.0) ); \n" " \n" " i -= 16.0; \n" " z = oldz; \n" " while( (i<256.0) && (dot(z,z) < 4.0) ) \n" " { \n" " z = vec2(z.x*z.x - z.y*z.y , 2.0*z.x*z.y ) + c; \n" " i+= 1.0; \n" " } \n" " float f = i / 256.0; \n" " gl_FragColor = texture1D(transfer_function, f ); \n" "} \n" ; int main(int argc, char* argv[]) { int i; SDL_Init( SDL_INIT_EVERYTHING ); SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); SDL_SetVideoMode( 1024, 1024, 0, SDL_OPENGL ); GLhandleARB prog; if ( !vr_glext_glsl_create_program(vshader,fshader_julia,&prog) ) return 0; // upload the transfer function texture GLuint tex_tf; glGenTextures(1,&tex_tf); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_1D); glBindTexture(GL_TEXTURE_1D, tex_tf); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, rainbow); glActiveTexture(GL_TEXTURE0); glDisable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_1D); glBindTexture(GL_TEXTURE_1D, tex_tf); eglUniform1iARB(eglGetUniformLocationARB(prog, "transfer_function"),0); glDisable(GL_CULL_FACE); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity (); glOrtho(0.,1., 0.,1.,-1.0,1.0); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glColor4f(1.0, 1.0, 1.0, 1.0); float p = 4.0; i=0; int before = SDL_GetTicks(); while(i<200) { eglUseProgramObjectARB(prog); glBegin(GL_QUADS); glTexCoord2f( -p, -p ); glVertex2f( 0.0, 0.0); glTexCoord2f( -p, p); glVertex2f( 0.0, 1.0); glTexCoord2f( p, p ); glVertex2f( 1.0, 1.0); glTexCoord2f( p, -p ); glVertex2f( 1.0, 0.0); glEnd(); SDL_GL_SwapBuffers(); i++; if (i>100) p*=1.05; else p/=1.05; } int after = SDL_GetTicks(); float time = (after-before)/1000.0; printf("%.2f seconds total (avg %.2f fps)\n",time,i/time); SDL_Quit(); }