Use a GLSL Shader

From JReality Wiki
Jump to: navigation, search

Source file: GLShadingLangExample01

JavaDoc: GlslProgram

JavaDoc: GlslPolygonShader


This tutorial includes three different examples. The first two illustrate using the GlslPolygonShader class; the third illustrates how to use the standard DefaultPolygonShader class.


Example 1

Run as Java webstart


The shading process in jReality is designed to accommodate customized shaders. For example, the JOGL backend supports polygon shaders written in the OpenGL Shading Language (or GLSL for short). The following example shows how to attach a GLSL shader to a jReality scene graph. It uses a publicly available GLSL brick shader which is also distributed with the jReality package.


When other backends rendering a scene graph where a GLSL shader appears, they use the default polygon shader.


...
 
public class GLShadingLangExample01 {
 
  public static void main(String[] args)  {
    SceneGraphComponent world = SceneGraphUtility.createFullSceneGraphComponent("world");
    Appearance ap = world.getAppearance();
    DefaultGeometryShader dgs = (DefaultGeometryShader) 
    ShaderUtility.createDefaultGeometryShader(ap, true);
    dgs.setShowLines(false);
    dgs.setShowPoints(false);
    dgs.createPolygonShader("glsl");
    GlslProgram brickProg = null;		
    world.setGeometry(SphereUtility.tessellatedIcosahedronSphere(3, true)); 
 
    try {
      brickProg = new GlslProgram(ap, "polygonShader",   
          Input.getInput("de/jreality/jogl/shader/resources/brick.vert"),
          Input.getInput("de/jreality/jogl/shader/resources/brick.frag")
          );
    } catch (IOException e) {
      e.printStackTrace();
    }
    double[] brickSize = {.2, .25};
    double[] brickPct = {.5, .75};
    double[] mortarPct = new double[2];
    double[] lightPosition = {-2,0,4};
    mortarPct[0] = 1.0 - brickPct[0];
    mortarPct[1] = 1.0 - brickPct[1];
    brickProg.setUniform("SpecularContribution", .5);
    brickProg.setUniform("DiffuseContribution", 1.0);
    brickProg.setUniform("BrickColor", new double[]{.2,0f,.8});
    brickProg.setUniform("MortarColor", new double[] {.8,1f,.2});
    brickProg.setUniform("BrickSize", brickSize);
    brickProg.setUniform("BrickPct", brickPct);
    brickProg.setUniform("MortarPct", mortarPct);
    brickProg.setUniform("LightPosition", lightPosition);      
    JRViewer.display(world);
  }
}

Example 2

Source file: GLShadingLangExample02


Run as Java webstart


This is another example showing how to create several different instances of the same GLSL brick shader.


The result should look like this:


GlslExample02.png


Example 3

Source file: GLShadingLangExample03


Run as Java webstart


In this example, you see how to activate GLSL shaders while using the DefaultPolygonShader. Additionally, you'll see how to access textures in your GLSL shader, which you loaded into jReality.


To use GLSL shaders with a DefaultPolygonShader, you need to do two things:

  • Create an instance of GlslProgram exactly as above, and
  • Rather than creating an instance of GlslPolygonShader as above, create a default polygon shader and set the appearance attribute "useGLSL" to true in the associated appearance.


		dgs.createPolygonShader("default");
    ....
//		dgs.createPolygonShader("glsl");
		ap.setAttribute("useGLSL", true);


In this example, the GLSL shader used here is only the fragment shader (meaning the standard OpenGL vertex shader will be used). Of course, you can also provide a vertex shader of your own as in the examples above. The fragment shader "sampler.frag" just looks up a color in a texture sampler and uses it as the fragment color.


Note that when using the default polygon shader, the geometry will be rendered using the older OpenGL style calls (including display lists if requested) rather than using vertex arrays.


The code also demonstrates how to pass a 2D texture sampler to the GLSL shader. Take a closer look at the code:

		ImageData id = stf.getImageData();
		Texture2D tex = TextureUtility.createTexture(ap, POLYGON_SHADER, 0, id);
		tex.setTextureMatrix(MatrixBuilder.euclidean().scale(5).getMatrix());
		try {
			brickProg = new GlslProgram(ap, "polygonShader",   
					null,
					Input.getInput("de/jreality/jogl/shader/resources/sampler.frag")
			    );
		} catch (IOException e) {
			e.printStackTrace();
		}
		brickProg.setUniform("sampler", 0);

You create a texture just as you would normally. The argument 0 identifies the texture unit to be used with this texture. You can also omit this argument; the default value is 0. This texture is then processed by the DefaultPolygonShader and loaded into the OpenGL state. So the setUniform method assigns same value 0 to the sampler uniform variable.


We load a second texture into the second texture unit using this code

    ImageData id = stf.getImageData();
    Texture2D gradTexture = TextureUtility.createTexture(ap, POLYGON_SHADER, 1, id);
    ...
    brickProg.setUniform("sampler", 1);

Currently


Note: The same idea should work with the GlslPolygonShader but doesn't currently work. (March 16, 2009).


Previous: Use a skybox and reflection map Developer Tutorial: Contents Next: Use vertex arrays in JOGL backend