PageRenderTime 107ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/PsychOpenGL/LoadGLSLProgramFromFiles.m

http://psychtoolbox-3.googlecode.com/
Objective C | 170 lines | 147 code | 23 blank | 0 comment | 35 complexity | dc95379112f6ab8a34f95a557e92e6b4 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.0
  1. function handle = LoadGLSLProgramFromFiles(filenames, debug, extraShaders)
  2. % handle = LoadGLSLProgramFromFiles(filenames [, debug] [, extraShaders])
  3. % Loads a GLSL OpenGL shading language program. All shader definition files in
  4. % 'filenames' are read, shaders are built for each definition and all
  5. % shaders are linked together into a new GLSL program. Returns a handle to
  6. % the new program, if successfull. The optional 'debug' flag allows to enable
  7. % debugging output: Zero = no output, 1 = a bit of outpt, 2 = detailed
  8. % output, 3 = Don't compile and link anymore, but print out the shaders
  9. % source code as OpenGL would see it.
  10. %
  11. % The program can then be used at any time by calling glUseProgram(handle). One
  12. % can switch back to the standard OpenGL fixed-function pipeline by calling
  13. % glUseProgram(0). The same handles can be passed to the
  14. % Screen('MakeTexture', ...), Screen('DrawTexture', ...); et al. routines
  15. % to define procedural textures - or some processing operations on them
  16. % via the 'textureShader' argument -- See 'help ProceduralShadingAPI' for
  17. % more info about procedural texturing. The handle is also used to build
  18. % GLOperators for Screen('TransformTexture') or as plugins for the imaging
  19. % pipeline: See 'help CreateGLOperator' or 'help AddToGLOperator' for info.
  20. %
  21. % 'filenames' can have one of two formats: If filenames is a array of
  22. % strings that define the names of the shaders to use, then all shader
  23. % files are loaded, compiled and linked into a single program. E.g.,
  24. % shaderfiles={ 'myshader.vert' , 'myothershader.frag'}; will try to load
  25. % the two shaderfiles myshader.vert and myothershader.frag and link them
  26. % into a valid program.
  27. %
  28. % If only a single filename is given, then all shaders beginning with that
  29. % name are linked into a program. E.g., shaderfiles = 'Phonglighting' will
  30. % try to link all files starting with Phonglighting.
  31. %
  32. % The optional argument 'extraShaders' if present, should be a vector of
  33. % additinal shader handles - Handles returned by the LoadShaderFromFile()
  34. % or by your self-compiled shaders via glCompileShader(). All precompiled
  35. % shaders referenced by those handles get also linked into the final GLSL
  36. % program.
  37. % 29-Mar-2006 written by MK
  38. global GL;
  39. if isempty(GL)
  40. % Load & Initalize constants and moglcore, but don't set the 3D gfx
  41. % flag for Screen():
  42. InitializeMatlabOpenGL([], [], 1);
  43. end;
  44. if nargin < 2
  45. debug = [];
  46. end;
  47. if isempty(debug)
  48. debug = 0;
  49. end
  50. if nargin < 1
  51. filenames = [];
  52. end
  53. if isempty(filenames)
  54. error('No filenames for GLSL program provided! Aborted.');
  55. end;
  56. if nargin < 3
  57. extraShaders = [];
  58. end
  59. % Make sure we run on a GLSL capable system.
  60. AssertGLSL;
  61. % Create new program object and get handle to it:
  62. handle = glCreateProgram;
  63. if handle <= 0
  64. fprintf('The handle created by glCreateProgram is %i -- An invalid handle!\n', handle);
  65. error('LoadGLSLProgramFromFiles: glCreateProgram failed to create a valid program object! Something is wrong with your graphics drivers!');
  66. end
  67. if ischar(filenames)
  68. % One single name given. Load and link all shaders starting with that
  69. % name:
  70. if debug>1
  71. fprintf('Compiling all shaders matching %s * into a GLSL program...\n', filenames);
  72. end;
  73. % Add default shader path if no path is specified as part of
  74. % 'filenames':
  75. if isempty(fileparts(filenames))
  76. filenames = fullfile(PsychtoolboxRoot,'PsychOpenGL','PsychGLSLShaders', filenames);
  77. end;
  78. % Fixup use of wrong fileseparators for platform:
  79. if IsWin
  80. prep = strfind(filenames, '/');
  81. filenames(prep) = filesep;
  82. else
  83. prep = strfind(filenames, '\');
  84. filenames(prep) = filesep;
  85. end
  86. shaderobjs=dir([filenames '*']);
  87. shaderobjpath = [fileparts([filenames '*']) filesep];
  88. numshaders=size(shaderobjs,1)*size(shaderobjs,2);
  89. if numshaders == 0
  90. fprintf('\n\n\nIn LoadGLSLProgramFromFiles: When trying to load shaders matching %s ...\n', filenames);
  91. error('Could not find any shader definition files matching that name. Check spelling.');
  92. end
  93. filenames=[];
  94. for i=1:numshaders
  95. [dummy1 curname curext] = fileparts(shaderobjs(i).name);
  96. shadername = [curname curext];
  97. filenames{i} = [shaderobjpath shadername]; %#ok<AGROW>
  98. end;
  99. end;
  100. % Any additional shader handles provided? If so, we attach them first,
  101. % before the shaders specified via files. Normally attachment order
  102. % shouldn't matter, but due to a driver bug in many 169.x and 175.x NVidia
  103. % drivers for Windows, it does. This is a known GLSL linker bug, cfe.
  104. %
  105. % http://www.stevestreeting.com/2007/12/27/nvidia-16921-driver-bug-in-glsl/
  106. %
  107. % The workaround is to attach shaders that define subfunctions (are part of
  108. % a library of common functions) first, before the shaders utilizing them.
  109. % Our color correction shaders are passed as extraShaders, so it is crucial
  110. % to attach extraShaders first to workaround this driver bug.
  111. if ~isempty(extraShaders)
  112. % Attach all of them as well:
  113. for i=1:length(extraShaders)
  114. glAttachShader(handle, extraShaders(i));
  115. end
  116. end
  117. % Load, compile and attach each single shader of each single file:
  118. for i=1:length(filenames)
  119. shadername = char(filenames(i));
  120. % We only load the shader if its name does not end in tilde or .asv,
  121. % because that would mean it is a Matlab- or emacs backup file...
  122. if (shadername(end)~='~') & (isempty(strfind(shadername, '.asv'))) %#ok<AND2>
  123. % Load, compile and link the shader:
  124. if debug < 3
  125. shdebug = 1;
  126. else
  127. shdebug = debug;
  128. end
  129. shader = LoadShaderFromFile(shadername, [], shdebug);
  130. glAttachShader(handle, shader);
  131. end;
  132. end;
  133. if debug > 1
  134. % We need to temporarily raise moglcores debuglevel to 2 to get extended
  135. % error/validation information:
  136. oldDebug = InitializeMatlabOpenGL(-1);
  137. moglcore('DEBUGLEVEL', 2);
  138. % Link the program:
  139. glLinkProgram(handle);
  140. % Restore old debuglevel for moglcore:
  141. moglcore('DEBUGLEVEL', oldDebug);
  142. else
  143. % Link the program without raised debug level for moglcore:
  144. glLinkProgram(handle);
  145. end
  146. % Ready to use it? Hopefully.
  147. return;