# GLSL dome shader

**URL:** <https://psychtoolbox.discourse.group/t/glsl-dome-shader/587>\
**Category:** Uncategorized\
**Created:** [October 10, 2019, 7:32pm UTC](https://psychtoolbox.discourse.group/t/glsl-dome-shader/587 "2019-10-10T19:32:52Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![baptistecaziot](https://avatars.discourse-cdn.com/v4/letter/b/46a35a/32.png) [@baptistecaziot](https://psychtoolbox.discourse.group/u/baptistecaziot)\
**Post date:** [October 10, 2019, 7:32pm UTC](https://psychtoolbox.discourse.group/t/glsl-dome-shader/587/1 "2019-10-10T19:32:52Z")

</div>

Hello.

I am trying to display a stimulus inside a dome using a GLSL shader. I use MOGL to display triangles on a 3D ground floor. This works fine. Then I tried to load a vertex and fragment shader, then use Screen('SetOpenGLTexture'... to apply the shader the shader to the active window, then draw the created texture back on the active window (this might be stupid, perhaps I can apply the shaders to the active window directly). But when I do that I just get a blank window. If I only load the shaders and do not try to apply them to a texture I also get a blank window so I suspect the shaders are the issue. I've never used shaders before so I'm having issues understanding how it all works. Could someone take a look or point me to examples on how to use shaders from the PTB? Thanks a lot.

Baptiste

  

  

Here is how I load the shaders:  

%% create shaders  
% vertex shader  
fid = fopen('DomeVertexShader.txt', 'r');  
vertexShaderSource = fread(fid);  
fclose(fid);  
vertexShader = glCreateShader(GL.VERTEX\_SHADER);  
glShaderSource(vertexShader, vertexShaderSource);  
glCompileShader(vertexShader);  
  
% fragment shader  
fid = fopen('DomeFragmentShader.txt', 'r');  
fragmentShaderSource = fread(fid);  
fclose(fid);  
fragmentShader = glCreateShader(GL.FRAGMENT\_SHADER);  
glShaderSource(fragmentShader, fragmentShaderSource);  
glCompileShader(fragmentShader);  
  
% create shader program  
shaderProgram = glCreateProgram;  
  
glAttachShader(shaderProgram, vertexShader);  
glAttachShader(shaderProgram, fragmentShader);  
glLinkProgram(shaderProgram);  
  
params = glGetProgramiv(shaderProgram, GL.LINK\_STATUS);  
[infoLength, infoLog] = glGetProgramInfoLog(shaderProgram, 512);  
  
glUseProgram(shaderProgram);  

Here is the loop where I draw triangles:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Screen('BeginOpenGL', window);  
  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glClear;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glPushMatrix;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluLookAt(cameraPosition(1)+(ee-0.5)\*pupilaryDistance, cameraPosition(2), cameraPosition(3), fixationPosition(1), fixationPosition(2), fixationPosition(3), cameraUp(1), cameraUp(2), cameraUp(3));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   
  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; % Draw floor triangles  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glBindBuffer(GL.ARRAY\_BUFFER, bufferFloorID);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glEnableClientState(GL.VERTEX\_ARRAY);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glBufferSubData(GL.ARRAY\_BUFFER, 0, bufferSize, floorVertLine);   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glNormalPointer(dataType, 0, bufferSize);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glVertexPointer(3, dataType, 0, 0);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glMaterialfv(GL.FRONT\_AND\_BACK, GL.DIFFUSE, trianglesColor);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glMaterialfv(GL.FRONT\_AND\_BACK, GL.AMBIENT, trianglesColor);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glDrawElements(GL.TRIANGLES, numFaces\*3, GL.UNSIGNED\_INT, int32(floorFacesLine-1));  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glDisableClientState(GL.VERTEX\_ARRAY);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glBindBuffer(GL.ARRAY\_BUFFER, 0);  
  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glPopMatrix;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Screen('EndOpenGL', window);

Here is when I try to apply the shader:  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; domedisplay = Screen('SetOpenGLTexture', window, [], 0, GL.TEXTURE\_RECTANGLE\_EXT, windowRect(3), windowRect(4), 1, shaderProgram);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Screen('DrawTexture',window,domedisplay,[-0.5\*windowRect(3),-0.5\*windowRect(4),windowRect(3),windowRect(4)],[]);

Here are the fragment and vertex shaders:

#version 120  
void main()  
{  
&nbsp; gl\_FragColor = vec4(1.0, 1.0, 1.0, 1.0);  
}

#version 120  
varying vec4 Vertex\_UV;  
uniform mat4 gxl3d\_ModelViewMatrix;  
uniform mat4 gxl3d\_ProjectionMatrix;  
  
uniform int do\_distorsion;  
  
const float PI = 3.1415926535;  
  
void main()  
{  
&nbsp; vec4 P = gxl3d\_ModelViewMatrix \* gl\_Vertex;  
&nbsp; if (do\_distorsion == 1)  
&nbsp; {&nbsp;   
&nbsp;&nbsp;&nbsp; float rxy = length(P.xy);  
&nbsp;&nbsp;&nbsp; if (rxy \> 0)  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float phi = atan(rxy, -P.z);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float lens\_radius = phi \* 180.0 / PI \* 2.0;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; P.xy \*= (lens\_radius / rxy);  
&nbsp;&nbsp;&nbsp; }  
&nbsp; }  
&nbsp; gl\_Position = gxl3d\_ProjectionMatrix \* P;  
&nbsp; Vertex\_UV = gl\_MultiTexCoord0 \* 10.0;  
}

Here is the stimulus if I don't load the shaders:

---

<div class="post-metadata">

**Author:** ![mariokleiner](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@mariokleiner](https://psychtoolbox.discourse.group/u/mariokleiner)\
**Post date:** [October 11, 2019, 4:57pm UTC](https://psychtoolbox.discourse.group/t/glsl-dome-shader/587/2 "2019-10-11T16:57:12Z")

</div>

Your code to load shader source and build a shader program can be replaced by a one-liner call to LoadGLSLProgramFromFiles(). Cfe. GLSLDemo.m

Where it goes sideways is when you create your texture and apply the shader. E.g., you specify a texture handle of zero instead of that of an actual texture - what texture? Probably you looked at a demo of ours that only uses shaders for procedural drawing but doesn't take any actual image input. Then a zero would make sense.  

  

I don't understand what you want to achieve, and your code is incomplete. But if the idea is somehow to render your triangle floor into a texture image and then draw that image into the onscreen window for display while applying some kind of shader, then the most easy way is to:

  

1. Open an Offscreen window via Screen('OpenOffscreenWindow', window, ...

2. Use 'BeginOpenGL' with the handle of that offscreen window.

3. Render your triangle thingy into the offscreen window.

4. 'EndOpenGL'

5. Now the offscreen window contains the rendered image of your triangle floor as a suitable PTB texture.

6. 'DrawTexture' that texture and pass in your shader programs handle to apply your shader to the texture during drawing.

7. Your shader only gets certain input parameters when called via 'DrawTexture', as explained in "help ProceduralShadingAPI" e.g.,

[http://psychtoolbox.org/docs/ProceduralShadingAPI](http://psychtoolbox.org/docs/ProceduralShadingAPI). Look at things like   

  

8. You can set those other parameters in your shader, which you currently don't do.

  

Ultimately you'd first have to explain in detail what you want to achieve here.

-mario  

  

  

> On Thu, Oct 10, 2019 at 9:36 PM [baptiste.caziot@...](mailto:baptiste.caziot@...) [PSYCHTOOLBOX] \<[PSYCHTOOLBOX@yahoogroups.com](mailto:PSYCHTOOLBOX@yahoogroups.com)\> wrote:  
> 
> > Hello.
> > 
> > I am trying to display a stimulus inside a dome using a GLSL shader. I use MOGL to display triangles on a 3D ground floor. This works fine. Then I tried to load a vertex and fragment shader, then use Screen('SetOpenGLTexture'... to apply the shader the shader to the active window, then draw the created texture back on the active window (this might be stupid, perhaps I can apply the shaders to the active window directly). But when I do that I just get a blank window. If I only load the shaders and do not try to apply them to a texture I also get a blank window so I suspect the shaders are the issue. I've never used shaders before so I'm having issues understanding how it all works. Could someone take a look or point me to examples on how to use shaders from the PTB? Thanks a lot.
> > 
> > Baptiste
> > 
> >   
> > 
> >   
> > 
> > Here is how I load the shaders:  
> > 
> > %% create shaders  
> > % vertex shader  
> > fid = fopen('DomeVertexShader.txt', 'r');  
> > vertexShaderSource = fread(fid);  
> > fclose(fid);  
> > vertexShader = glCreateShader(GL.VERTEX\_SHADER);  
> > glShaderSource(vertexShader, vertexShaderSource);  
> > glCompileShader(vertexShader);  
> >   
> > % fragment shader  
> > fid = fopen('DomeFragmentShader.txt', 'r');  
> > fragmentShaderSource = fread(fid);  
> > fclose(fid);  
> > fragmentShader = glCreateShader(GL.FRAGMENT\_SHADER);  
> > glShaderSource(fragmentShader, fragmentShaderSource);  
> > glCompileShader(fragmentShader);  
> >   
> > % create shader program  
> > shaderProgram = glCreateProgram;  
> >   
> > glAttachShader(shaderProgram, vertexShader);  
> > glAttachShader(shaderProgram, fragmentShader);  
> > glLinkProgram(shaderProgram);  
> >   
> > params = glGetProgramiv(shaderProgram, GL.LINK\_STATUS);  
> > [infoLength, infoLog] = glGetProgramInfoLog(shaderProgram, 512);  
> >   
> > glUseProgram(shaderProgram);  
> > 
> > Here is the loop where I draw triangles:  
> > Screen('BeginOpenGL', window);  
> >   
> > glClear;  
> > glPushMatrix;  
> >   
> > gluLookAt(cameraPosition(1)+(ee-0.5)\*pupilaryDistance, cameraPosition(2), cameraPosition(3), fixationPosition(1), fixationPosition(2), fixationPosition(3), cameraUp(1), cameraUp(2), cameraUp(3));   
> >   
> > % Draw floor triangles  
> > glBindBuffer(GL.ARRAY\_BUFFER, bufferFloorID);  
> > glEnableClientState(GL.VERTEX\_ARRAY);  
> > glBufferSubData(GL.ARRAY\_BUFFER, 0, bufferSize, floorVertLine);   
> > glNormalPointer(dataType, 0, bufferSize);  
> > glVertexPointer(3, dataType, 0, 0);  
> > glMaterialfv(GL.FRONT\_AND\_BACK, GL.DIFFUSE, trianglesColor);  
> > glMaterialfv(GL.FRONT\_AND\_BACK, GL.AMBIENT, trianglesColor);  
> > glDrawElements(GL.TRIANGLES, numFaces\*3, GL.UNSIGNED\_INT, int32(floorFacesLine-1));  
> > glDisableClientState(GL.VERTEX\_ARRAY);  
> > glBindBuffer(GL.ARRAY\_BUFFER, 0);  
> >   
> > glPopMatrix;  
> >   
> > Screen('EndOpenGL', window);
> > 
> > Here is when I try to apply the shader:  
> > domedisplay = Screen('SetOpenGLTexture', window, [], 0, GL.TEXTURE\_RECTANGLE\_EXT, windowRect(3), windowRect(4), 1, shaderProgram);  
> > Screen('DrawTexture',window,domedisplay,[-0.5\*windowRect(3),-0.5\*windowRect(4),windowRect(3),windowRect(4)],[]);
> > 
> > Here are the fragment and vertex shaders:
> > 
> > #version 120  
> > void main()  
> > {  
> > gl\_FragColor = vec4(1.0, 1.0, 1.0, 1.0);  
> > }
> > 
> > #version 120  
> > varying vec4 Vertex\_UV;  
> > uniform mat4 gxl3d\_ModelViewMatrix;  
> > uniform mat4 gxl3d\_ProjectionMatrix;  
> >   
> > uniform int do\_distorsion;  
> >   
> > const float PI = 3.1415926535;  
> >   
> > void main()  
> > {  
> > vec4 P = gxl3d\_ModelViewMatrix \* gl\_Vertex;  
> > if (do\_distorsion == 1)  
> > {   
> > float rxy = length(P.xy);  
> > if (rxy \> 0)  
> > {  
> > float phi = atan(rxy, -P.z);  
> > float lens\_radius = phi \* 180.0 / PI \* 2.0;  
> > P.xy \*= (lens\_radius / rxy);  
> > }  
> > }  
> > gl\_Position = gxl3d\_ProjectionMatrix \* P;  
> > Vertex\_UV = gl\_MultiTexCoord0 \* 10.0;  
> > }
> > 
> > Here is the stimulus if I don't load the shaders:
> > 
> > ![]()
> > 
> > And if I do (regardless of whether I try to apply the transform or not):
> > 
> > ![]()

---

<div class="post-metadata">

**Author:** ![baptistecaziot](https://avatars.discourse-cdn.com/v4/letter/b/46a35a/32.png) [@baptistecaziot](https://psychtoolbox.discourse.group/u/baptistecaziot)\
**Post date:** [October 11, 2019, 9:01pm UTC](https://psychtoolbox.discourse.group/t/glsl-dome-shader/587/3 "2019-10-11T21:01:49Z")

</div>

Hi Mario.

I attached a picture of the stimulus in my previous email but it disappeared. In short, we use a stimulus that is basically a RDK made of triangles displayed on a 2D ground floor. The observers move on that ground plane to get to a disk target using a joystick. Until now we displayed the stimulus on a regular (flat) display screen, but in the future we would like to display that stimulus inside a dome using a projector. So I would like to distort the openGL window on which I draw the stimulus so that once projected on the spherical inside of the dome it is geometrically correct. After some research it seems shaders would be a good way to apply this geometrical transformation fast. But again, I am new to these things.

  

I've tried to implement your suggestions. I managed to draw on a offscreen texture but only if I turn off multisampling. If I understand correctly I should use the shader when calling DrawTexture and pass arguments to the shader through auxParameters? Or I could define these parameters inside the shader itself (I assume that would be the projection and view matrices)? I grabbed these shaders somewhere on the internet and I don't fully understand how they work yet.

  

I attached the script I wrote to generate the stimulus and a modified one with the offscreen window, as well as the shaders. Also, we display the stimulus in stereo (sequential but here I used anaglyph).  

Regards,

Baptiste
