LimpetGE Logo

LimpetGE Shader Reference

The LimpetGE shader reference manual. This is not about actually writing shaders, but how to incorporate them into the LimpetGE framework.

Overview

Each "shader" has it's information contained in a constant javascript object. Each contains the following properties:

keyA unique key number for the shader. It is usually (re)generated when compiling the script.
vertexSourceThe Vertex Shader source code
fragSourceThe fragment shader source code
compile()Compiles the Fragment and Vertex programs. It also "binds" the shader's uniform and attribute locations, usually into a "sub-object" called "locations" on the shader object. Called once when initialising the LimpetGE environment (in "lInit()")
doInitBuffer(structure)A function, that has a structure as it's argument. It assembles the OpenGL buffers from the Points, Normals and Texture coordinates arrays. These are then stored in the "buffer" property (also a Javascript object) on the structue class. Related information to the buffers are stored there too. Called for each structure when structures are complete.
useProgram()A function, when called, is a wrapper around the OpenGL "useProgram" program. Called once in each frame.
useBuffer(buffer)Takes the structure's buffer as the argument. It binds the buffer information to the uniform shader locations. It is called once per frame per structure.
doDraw(buffer, position, control)Takes the structure's buffer, a "mat4" position and a game object's control as the arguments. This binds any "last minute" uniform or attributes, and does OpenGL's "drawElements(....)" routine (or equivalent). Called once per frame per object.

There is a global variable that needs to exist and be set as well:

lShader_objects - This is an array of shaders used, in the order there objects are to be drawn.

Best way to include a new shader in LimpetGE

Take one, copy it, and modify it.


The vertesSource and fragSource properties

These are the "Fragment Shader" and "Vertex Shader" sources as strings. I will not go into these, there is resource on the web how to write these.

The compile() function

This is esponsible for compiling the shaders and binding the uniform and attribute locations.

To compile, there is a LimpetGE helper function "lInitShaderProgram(fragmentSource, vertexSource)". The definition of this is:

lInitShaderProgram(vertexSource, fragmentSource)Compile the shader sources
vertexSourceThe source for the vertex shader
fragmentSourceThe source for the fragment shader
Returns the compiled program. Usually stored in the "shader" property of the shader object.

The locations are normally bound to variables in a created object, which is then stored in the "locations" property of the Shader Object.

To understand this, it is probably best to look at the shader objects supplied.


The doInitBuffer(structure) function

This taks the structure (as created by "new LStructureDef") as the argument. It is called uring the "lStructureSetup()" function, which is automatically called for all structures that have not had this called before. That function is called in the creation of the "Scene" instance is created: a class that is derived from the "LBase" class. If for some reason it is to be "re-initialised" he user can set the "compiled" property on the structure to "false", and call "lStructureSetup()" again, or create a new "Scene".

The relevant property arrays, and associated information, supplied by the structure are:

structure.argsThe "object named arguments" passed to the LStructureDef constructor when created.
structure.pointsArrayAn array containing the coordinates of the vertices (just the x, y and z, no w).
structure.normalsArrayAn array containing the corresponding normals for the vertices (x, y and z).
structure.coordsArrayAn array of The coordinates in the texture collage supplied (u, v) - values between 0.0 and 1.0.
structure.pointsIndexAn array of the indexes to be used as the controlling OpenGL "drawElements" function.
structure.numentriesThis is the length of the "pointsIndex" array.

While processing what is passed in "args", the following from the LimpetGE javascript may be useful:

lLoadTexture(url)Load a texture from a URL and return it
urlThe URL of the appropriate image to load.
lLoadColor(color)Create a texture containing a one pixel image and return it
colorThe color ("vec4") to use.
lLoadColors(colors, width, height)Create a texture containing a (width * height) pixel image and return it
colorsAn array of "vec4" arrays representing colors. The number of these should equal width multiplied by height.
widthThe width in pixels of the image
heightThe height in pixels of the image. This is usually one, and nothing is achieved by using anything else. The "ltextureColor" helper function assumes this.

It is at this point you can pass alternative textures (a more bloody face as an entity gets more injured, etc), and the such.

The arrays need to go through the "bind" process, a reference stored on an object that is stored in the "buffer" property of the structure.

Again, to understand this, it is probably best to look at the shader objects supplied.


The useProgram() function

A wrapper to the OpenGL's "useProgram(shader)" function. The "shader" program is usually in the "shader" property of the object, if not, it is where you put it in the "compile()" function.


The useBuffer(buffer) function

This is called once per frame per structure. It performs the "bind" process of the arrays in the "buffer" (created in "doInitBuffer(...)" above) onto the OpenGL "locations" (created in the "compile()" function above). It also binds any uniform locations, remembering there is access to the "Scene" objects (using the global "lScene" variable that stores a reference to it).

Again, to understand this, it is probably best to look at the shader objects supplied.


The doDraw(buffer, position, control) function

This draws the object, the arguments:

bufferThe "buffer" property of structure
positionThe scene transformation position ("mat4") where this object is to be placed.
controlAn object that is the "control" of the object, as defined when creating the "new LObject(structure, control)" instance.

This functions needs to call the OpenGL "drawElements(...)" function (or whatever), and do the "last minute" preparations for that (binding the scene position and the like).

Again, with dnger to repeating myself, to understand this, it is probably best to look at the shader objects supplied.


the lShader_objects array

This is a constant global array. It lists the shader object references in the order they are to be drawn (transparent ones last).


Donate