function GLSLDemo % GLSLDemo - Demonstrate use of the GLSL OpenGL Shading language in the % Psychtoolbox. % % The OpenGL shading language (GLSL) allows to write specialized programs % which are uploaded into the graphics hardware itself. These programs % are then executed very efficiently in the grahpics hardware. So called % Vertex-Shaders are executed on a per-vertex basis. They calculate and % manipulate per-vertex properties, e.g., displacement, color, normal % vectors. So called Fragment-Shaders are executed for each single fragment % or pixel that is drawn into the backbuffer. They allow, e.g., to implement % your own lighting model or perform image processing on your image. % % GLSL programs are very similar in their syntax to the C programming language, % its basically C, extended by functions for matrix and vector math and for % typical graphics purpose. % % A specific piece of graphics hardware may only support either vertex-shaders, % or fragment-shaders or none at all, as these features are pretty new in the % world of computer-graphics, so this demo may not run at all or at least some % shaders will either fail or give unexpected results. If you want to make % use of GLSL you'll need to equip your computer with up to date graphics % hardware. % % This demo loads a collection of shaders. It applies the shaders to a % collection of objects, demonstrating some visual effects. This is early % beta code, so don't expect too much. It mostly demonstrates how to get % started with shader-programming in Psychtoolbox. % % Press the 'n' key to toggle between different objects. % Press the SPACE key to toggle between the different shaders. % Stop the demo by pressing any other key. % Online specs for GLSL can be found under: % % % This: % % is a very nice introduction into GLSL. % % Apart from that, theres the standard book on GLSL by Addison Wesley: % "OpenGL(R) Shading Language (2nd Edition)" this is also known as % "The Orange book". % % Written by Mario Kleiner. % Is the script running in OpenGL Psychtoolbox? AssertOpenGL; % Find the screen to use for display: screenid=max(Screen('Screens')); % Disable Synctests for this simple demo: Screen('Preference','SkipSyncTests',1); % Setup Psychtoolbox for OpenGL 3D rendering support and initialize the % mogl OpenGL for Matlab wrapper: InitializeMatlabOpenGL(1); % Open a double-buffered full-screen window on the main displays screen. [win , winRect] = Screen('OpenWindow', screenid); % Make sure we run on a GLSL capable system. Abort if not. AssertGLSL; % Setup the OpenGL rendering context of the onscreen window for use by % OpenGL wrapper. After this command, all following OpenGL commands will % draw into the onscreen window 'win': Screen('BeginOpenGL', win); % Get the aspect ratio of the screen: ar=winRect(4)/winRect(3); % Turn on OpenGL local lighting model: The lighting model supported by % OpenGL is a local Phong model with Gouraud shading. glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); % Enable the first local light source GL_LIGHT_0. Each OpenGL % implementation is guaranteed to support at least 8 light sources. glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); % Enable two-sided lighting - Back sides of polygons are lit as well. glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); % Enable proper occlusion handling via depth tests: glEnable(GL_DEPTH_TEST); % Define the cubes light reflection properties by setting up reflection % coefficients for ambient, diffuse and specular reflection: glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT, [ 0.88 0.1 0.88 1 ]); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE, [ .22 .27 .9 1 ]); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR, [ 1 1 1 1 ]); glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS, 2); % Set projection matrix: This defines a perspective projection, % corresponding to the model of a pin-hole camera - which is a good % approximation of the human eye and of standard real world cameras -- % well, the best aproximation one can do with 3 lines of code ;-) glMatrixMode(GL_PROJECTION); glLoadIdentity; % Field of view is +/- 25 degrees from line of sight. Objects close than % 0.1 distance units or farther away than 100 distance units get clipped % away, aspect ratio is adapted to the monitors aspect ratio: gluPerspective(25,1/ar,0.1,100); % Setup modelview matrix: This defines the position, orientation and % looking direction of the virtual camera: glMatrixMode(GL_MODELVIEW); glLoadIdentity; % Cam is located at 3D position (0,0,10), points upright (0,1,0) and fixates % at the origin (0,0,0) of the worlds coordinate system: gluLookAt(0,0,10,0,0,0,0,1,0); % Setup position and emission properties of the light source: % Set background color to 'black': glClearColor(0,0,0,0); % Point lightsource at (1,2,3)... glLightfv(GL_LIGHT0,GL_POSITION,[ 20 200 20 0 ]); % Emits white (1,1,1,1) diffuse light: glLightfv(GL_LIGHT0,GL_DIFFUSE, [ 0.4 0.4 0.9 1 ]); % Emits reddish (1,1,1,1) specular light: glLightfv(GL_LIGHT0,GL_SPECULAR, [ 1 1 1 1 ]); % There's also some blue, but weak (R,G,B) = (0.1, 0.1, 0.1) % ambient light present: glLightfv(GL_LIGHT0,GL_AMBIENT, [ .0 .0 .9 1 ]); % Point lightsource at (1,2,3)... glLightfv(GL_LIGHT1,GL_POSITION,[ 20 -200 20 0 ]); % Emits white (1,1,1,1) diffuse light: glLightfv(GL_LIGHT1,GL_DIFFUSE, [ 0.8 0.8 0.2 1 ]); % Emits reddish (1,1,1,1) specular light: glLightfv(GL_LIGHT1,GL_SPECULAR, [ 1 1 1 1 ]); % There's also some blue, but weak (R,G,B) = (0.1, 0.1, 0.1) % ambient light present: glLightfv(GL_LIGHT1,GL_AMBIENT, [ .0 .0 .9 1 ]); glEnable(GL_NORMALIZE); % GLSL setup: glGetError; % Load all pairs of GLSL shaders from the directory of demo shaders and % create GLSL programs for them: LoadGLSLProgramFromFiles is a convenience % function. It loads single shaders or multiple shaders from text files, % compiles and links them into a GLSL program, checks for errors and - if % everything is fine - returns a handle that can be used to enable the % GLSL program via glUseProgram(): shaderpath = [PsychtoolboxRoot '/PsychDemos/OpenGL4MatlabDemos/GLSLDemoShaders/']; glsl(1)=LoadGLSLProgramFromFiles([shaderpath 'Flattenshader'],1); glsl(2)=LoadGLSLProgramFromFiles([shaderpath 'Pointlightshader'],1); glsl(3)=LoadGLSLProgramFromFiles([shaderpath 'Toonshader'],1); glsl(4)=LoadGLSLProgramFromFiles([shaderpath 'Brickshader'],1); gluErrorString % Activate program: glUseProgram(glsl(1)); programid = glsl(1); programmax = length(glsl); gluErrorString % Initialize amount and direction of rotation theta=0; rotatev=[ 0 0 1 ]; objectid=0; % Animation loop: Run until key press... while (1) % Calculate rotation angle for next frame: theta=mod(theta+0.03,360); rotatev=rotatev+0.01*[ sin((pi/180)*theta) sin((pi/180)*2*theta) sin((pi/180)*theta/5) ]; rotatev=rotatev/sqrt(sum(rotatev.^2)); % Setup cubes rotation around axis: glPushMatrix; glRotated(theta,rotatev(1),rotatev(2),rotatev(3)); % Clear out the backbuffer: This also cleans the depth-buffer for % proper occlusion handling: glClear; switch mod(objectid, 8) case 0 glutSolidCube(1.0); case 1 glutSolidTeapot(1.0); case 2 glutSolidSphere(1, 50, 10); case 3 glutSolidTorus( 0.7, 1, 100, 100 ) case 4 glutWireCube(1.0); case 5 glutWireTeapot(1.0); case 6 glutWireSphere(1, 50, 10); case 7 glutWireTorus( 0.7, 1, 100, 100 ) end; glPopMatrix; % Finish OpenGL rendering into PTB window and check for OpenGL errors. Screen('EndOpenGL', win); % Show rendered image at next vertical retrace: Screen('Flip', win); % Switch to OpenGL rendering again for drawing of next frame: Screen('BeginOpenGL', win); % Check for keyboard press and exit, if so: [keydown secs keycode]=KbCheck; if keydown if keycode(KbName('n')) % Toggle objectid: objectid=objectid+1; elseif keycode(KbName('space')) % Toggle/Switch use of GLSL shaders: programid = mod(programid + 1, programmax+1); if programid > 0 % Enable shaders: glUseProgram(glsl(programid)); else % Disable shaders: glUseProgram(0); end; else break; end; % Debounce keys: while KbCheck; end; end; end % Shut down OpenGL rendering: Screen('EndOpenGL', win); % Close onscreen window and release all other ressources: sca; % Reenable Synctests after this simple demo: Screen('Preference','SkipSyncTests',1); % Well done! return