Create A Basic Shader

You need the following Simdify® modules to complete this exercise: Simdify® Free Edition, Microsoft® Visual Studio® 2017 or newer (to export).

In this exercise you'll learn to create an application layout that renders geometry with a vertex and fragment shader. After creating the application, you'll learn how to export it to Windows® and compile it with Microsoft Visual Studio®. You can follow this exercise, even if you don't intend to export it at the end.

Start The Layout Application

  1. Start the Layout app. (Start » Programs » Scenomics » Layout) or (Windows® key and then type 'Layout' to find the app icon.)

    The application displays a splash screen and then the application desktop appears. The main menu is composed of three items since this is an empty document. More interface options become available when you create a new file or load a file from disk.

    This is a picture of the desktop.

Create New Document

  1. Select File » New » Layout from the main menu.

    The software displays a wizard that allows you to specify the parameters of your new shader. The Profile shown below is 460 core, but you will see the highest GLSL version available on your machine.

    NOTE: You will not see video or compute shader options in the wizard dialog if you do have not purchased the compute or video add-on modules.

    This is a picture of the new project dialog.
  2. Type Simple Application Layout in the field named Name.

    Copy Text To Clipboard

    User Basic Shader
  3. Set Profile to the highest value available such as 460 core. If they are present, leave the compute and video options set to false.
  4. Leave Shader Prefix set to visual.
  5. Hit ENTER or click OK when you are finished.

    The application creates a new application layout document and the main menu options change. You can see the hierarchy on the left, the rendered shader with geometry in the middle, and the property sheet on the right. GLSL compiler messages are shown in the output window below. The shader sets the fragment color to red and does no other work.

    This is a picture of the workspace.

    If the shader compiled successfully, you should see a red square in the center of the worksheet.

  6. Select File » Save from the main menu.

Examine The New Document

  1. Select Desktop » Clear Output from the main menu.
  2. Examine the main menu and select Graph » State » Expand All Tree Items. ( Or hit ALT + X ).

    This expands the graph so that you can see all the nodes. As you can see, this application is made from a set of nodes. Nodes are atomic types because there is no smaller element that can be used in the layout.

    NOTE: You can hover over each node icon, in the image below, for a description of the node and its function.

    In this simple example, program and mesh resources are declared inside invisible sections of the document. Then in the visible sections, the shader is activated and uniform values are set. Finally, the mesh is rendered. This is the most important pattern in any layout.

    1. Activate a <Program>.
    2. Write uniforms, buffers, textures.
    3. Render something.
    4. (Optionally) Deactivate the <Program>.
  3. In the running Layout app, move the mouse over the <Program> node named Visual.

    Notice that you can see the GLSL version, profile, and source code locations. Many nodes, but not all of them, display useful information if you hover over them.

    This is a picture of the Program node info tip.

Copy The Fragment Shader Path

  1. Examine the hierarchy and right click over the <Program> node named Visual. This is a picture of the Program node command menu.
  2. Choose Copy Source Path » Fragment Shader from the listed options.

    This displays a dialog that allows you to select GLSL shader source code (and any include files). The file path of the source item you select will be copied to the Windows® clipboard so you can open it in a text editor.

    This is a picture of the source code used by the <Program> node fragment shader.
  3. Select visual_fragment_shader.glsl and click OK or hit ENTER when you are finished.

    This copies the absolute path to the fragment shader source code to the Windows® clipboard. For example, a file path like the following: C:\Users\MyUserName\MyDocuments\Scenomics\Shader\Simple Application Layout\460\visual_fragment_shader.glsl is copied to the clipboard.

Modify Fragment Shader

  1. Start a text editor of your choice and select the option to open a file from disk.
  2. Select CTRL + V to paste the fragment shader file path (into the place in the dialog where you specify the file to open) and open the file.

    This is the fragment shader. Note that your #version 460 declaration might be different, depending on the highest GLSL version on your machine. You can still follow this exercise even if the shader code is different. Just follow the steps below and make the same changes in the same locations.

    // #version 460
    // The version number is automatically injected by the application.
    // It is included above for reference purposes only.
    #include <SPA_Version.glsl>
    #include <SPA_Constants.glsl>
    #include <Modules/SPA_EditStateFragmentColorOverride.glsl>
    #include "visual_attributes.glsl"
    
    in Data { vertexData attributes; } DataIn;
    out vec4 fragColor;
    
    void main(void)
    {
       fragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
       SPA_EditStateFragmentColorOverride( fragColor );
    }
    

    Simdify supports #include for GLSL. This makes life a lot easier when you're writing shader code. You can dump the fully assembled translation unit at any time if you need to see all your shader code, or when you are ready to take the shader code and use it in your own applications.

    Notice that there is a line #include <Modules/SPA_EditStateFragmentColorOverride.glsl> and a corresponding line SPA_EditStateFragmentColorOverride( fragColor ); at the end of the shader. This is necessary for the Magnifier draw mode to work. The Magnifier draw mode powers the compute shader and texture debugging tools. If you're using these shaders for other purposes, or if you don't need to debug, you can remove the include statement and the call to SPA_EditStateFragmentColorOverride( fragColor ). Removing this code won't affect how your shader works.

  3. Find the following line, where a color value is assigned to the output fragment color:

    fragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
    
  4. Change the code to the following:

    Copy Text To Clipboard

    fragColor = vec4( DataIn.attributes.texcoord, 1.0, 1.0 );

    Note that if you're using an older version of GLSL in this exercise, the replacement code might be something like this:

    Copy Text To Clipboard

    fragColor = vec4( fs_texcoord, 1.0, 1.0 );

  5. Save the changes to the fragment shader.

    Leave the fragment shader open in the text editor.

Examine The Document

  1. Return to the running Layout application. The color has changed from red to a blue, white, and purple gradient, which shows us the shader pipeline is active and that we can make more changes. This is a picture of the workspace.

Declare A Uniform

  1. Return to the text editor and examine the fragment shader.
  2. Add the following code immediately above out vec4 fragColor

    Copy Text To Clipboard

    uniform vec4 tint_color;
    Your fragment shader code looks like this:

    // #version 460
    // The version number is automatically injected by the application.
    // It is included above for reference purposes only.
    #include <SPA_Version.glsl>
    #include <SPA_Constants.glsl>
    #include <Modules/SPA_EditStateFragmentColorOverride.glsl>
    #include "user_basic_attributes.glsl"
    
    in Data { vertexData attributes; } DataIn;
    uniform vec4 tint_color;
    out vec4 fragColor;
    
    void main(void)
    {
       fragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
       SPA_EditStateFragmentColorOverride( fragColor );
    }
    
  3. Modify the assignment to the fragment color:

    Copy Text To Clipboard

    fragColor = tint_color;
    Your fragment shader main function looks like this:

    void main(void)
    {
       fragColor = tint_color;
       SPA_EditStateFragmentColorOverride( fragColor );
    }
    
  4. Save the changes to the fragment shader.

    Leave the fragment shader open in the text editor.

Add The Uniform

  1. Return to the running Layout application.

    The rendered geometry is going to turn black when you return to the application. Depending on the behavior of your graphics driver you may see other colors as well. This is because we have not yet set a value for uniform vec4 tint_color. We're going to create a resource for this uniform next.

  2. Examine the hierarchy and find the <ProgramBindNode> named Bind Visual. This is a picture of the graph.

    This binds the program to the rendering device and activates it. Once the program is in an active state, we can set uniforms and do other things.

  3. Right click over the <ProgramBindNode> named Bind Visual and select Create Source Code Item... from the listed options.

    The software presents a dialog that allows you to add resources that have been declared in your GLSL code.

    This is a picture of the Create Source Code Item dialog.
  4. Left click uniform vec4 tint_color and click OK or hit ENTER when you are finished.

    The software adds a <Float32VectorNode> named uniform vec4 tint_color to the layout.

    This is a picture of the hierarchy showing the new tint color uniform.

Edit The <Float32VectorNode>

  1. Examine the hierarchy.
  2. Right click the <Float32VectorNode> named uniform vec4 tint_color and select Edit... from the listed options.

    This displays the <Float32VectorNode> property editor.

    This is a picture of the Float32Vector property editor.
  3. Set the Component[0] to 0.5.
  4. Set the Component[1] to 1.0.
  5. Set the Component[2] to 0.5.
  6. Set the Component[3] to 1.0.
  7. Click OK to dismiss the editor.

    The worksheet looks like this:

    This is a picture of the worksheet.

    This is generally how you set uniform values. You declare them in the shader and then add then to the document. In versions of GLSL higher than 120, you can also initialize uniforms when you declare them. If initialized in GLSL, the values of the <VariableNode> in the Layout app will match the initializer values you typed in the shader code. You can then configure the values of the new nodes to suit your purpose. Many uniform values are set by the user, as we just did, but later you'll learn about using <DataCapture> objects to capture values from the document and use them as uniform values. The other way to create uniforms, uniform buffers, is discussed in a subsequent exercise (but it requires the Simdify Compute+ Module).

Declare A Texture Sampler

  1. Return to the text editor and examine the fragment shader.
  2. Add the following code immediately after uniform vec4 tint_color

    Copy Text To Clipboard

    uniform sampler2D diffuse_texture;

    Your fragment shader code looks like this:

    // #version 460
    // The version number is automatically injected by the application.
    // It is included above for reference purposes only.
    #include <SPA_Version.glsl>
    #include <SPA_Constants.glsl>
    #include <Modules/SPA_EditStateFragmentColorOverride.glsl>
    #include "user_basic_attributes.glsl"
    
    in Data { vertexData attributes; } DataIn;
    uniform vec4 tint_color;
    uniform sampler2D diffuse_texture;
    out vec4 fragColor;
    
    void main(void)
    {
       fragColor = tint_color;
       SPA_EditStateFragmentColorOverride( fragColor );
    }
    
  3. Insert the texture sampling code immediately above the assignment to fragColor:

    Copy Text To Clipboard

    vec4 diffuse_color = texture( diffuse_texture, DataIn.attributes.texcoord );

    Your fragment shader main function looks like this:

    void main(void)
    {
       vec4 diffuse_color = texture( diffuse_texture, DataIn.attributes.texcoord );
       fragColor = tint_color;
       SPA_EditStateFragmentColorOverride( fragColor );
    }
    

    This code samples a texture using the texture coordinates computed by the vertex shader.

  4. Modify the assignment to the fragment color to multiply diffuse_color by tint_color:

    Copy Text To Clipboard

    fragColor = diffuse_color * tint_color;

    Your fragment shader main function looks like this:

    void main(void)
    {
       vec4 diffuse_color = texture( diffuse_texture, DataIn.attributes.texcoord );
       fragColor = diffuse_color * tint_color;
       SPA_EditStateFragmentColorOverride( fragColor );
    }
    
  5. Save the changes to the fragment shader.

    Leave the fragment shader open in the text editor.

Add The Sampler

  1. Return to the running Layout application.
  2. Examine the hierarchy and find the <ProgramBindNode> named Bind Visual. This is a picture of the graph.
  3. Right click over the <ProgramBindNode> named Bind Visual and select Create Source Code Item... from the listed options.

    The software presents a dialog that allows you to add resources that have been declared in your GLSL code.

    This is a picture of the Create Source Code Item dialog.
  4. Left click uniform sampler2D diffuse_texture and click OK or hit ENTER when you are finished.

    The software adds a <SamplerNode> to the layout.

    This is a picture of the hierarchy showing the new sampler.

Load A Texture From Disk

  1. Examine the hierarchy.
  2. Right click over the <SamplerNode> named uniform sampler2D diffuse_texture and select Load Texture From Disk... from the listed options.

    This displays the file open dialog, which allows you to choose a 2D texture from the hard disk. There is a list of folders that organize textures by pixel format.

    This is a picture of the file open dialog.
  3. Type IPF_8888_ARGB to enter the folder containing textures of this pixel format.

    Copy Text To Clipboard

    IPF_8888_ARGB
  4. Type IPF_8888_ARGB.png and click Open or hit ENTER when you are finished.

    Copy Text To Clipboard

    IPF_8888_ARGB.png

Examine The Results

  1. Select Graph » State » Expand All Tree Items from the main menu.

    The software adds a <Texture> node named IPF_8888_ARGB to the document and connects the <SamplerNode> to the new texture.

    This is a picture of the graph.

    You can see the texture modified by the tint color. If you change the tint color uniform, then the results on screen will change.

    This is a picture of the desktop.
  2. Select File » Save from the main menu.

Export The Application

  1. Select File » Export » Windows 64-Bit from the main menu.

    The software displays a dialog that allows you to export the application layout as a standalone Windows graphics application.

    This is a picture of the Windows export dialog.

    By default, the export is configured to generate the exported document in a sub-directory of the folder containing the .BOX document that implements the shader.

  2. Click OK or hit ENTER to proceed.

    The software exports the document. The export process generates the C++, GLSL, and Visual Studio solution files required to run the shader as a stand-alone graphics application.