As you may know, most of graphics hardware now allow processing of user code directly on the GPU. This means two things:
- You can relieve the CPU from performing some graphics-related computation by letting the GPU perform those computations and thus gain overall performance in your app.
- You can achieve beautiful graphic effects by modifying the per-pixel rendering process.
Those little pieces of code you can upload to the GPU are called shaders.
Gideros uses a shader system (a programmable pipeline). Gideros users can access the shaders system themselves, opening a broad range of possibilities. The rendering pipeline has several chained processing stages, which is why we call it a pipeline. A few stages are programmable, each requiring a particular type of program or shader. Gideros uses and lets user access two of them: the vertex shader and the fragment shader (also called pixel shader).
Each shader process one or more stream of data, which we will call attributes as per OpenGL semantics, and further produce one of more stream of (processed) data. Each shader also has access to one or more constants called uniforms. Those constants are settable at will before invoking the shader program, so that they are in fact only constants from the shader program point of view, and because their values can’t be changed in the middle of the processing of a stream of data.
Creating a shader
If you write your shader in Lua then it will automatically be re-written in the appropriate shader language for the platform. This makes it ideal for games that are multi-platform as you only have to code the shader once.
Typical Lua Vertex and Fragment shader code:
function vertex(vVertex,vColor,vTexCoord) local vertex = hF4(vVertex,0.0,1.0) fTexCoord=vTexCoord return vMatrix*vertex end function fragment() local frag=lF4(fColor)*texture2D(fTexture, fTexCoord) local coef=lF3(0.2125, 0.7154, 0.0721) local gray=dot(frag.rgb,coef) frag.rgb=lF3(gray,gray,gray) if (frag.a==0.0) then discard() end return frag end
In order to change the value of a uniform from lua, use the setConstant function. It takes three arguments:
- The uniform name.
- The type of data to set (one of the Shader.Cxxx constants).
- And the actual data to set, either as a table or as multiple arguments.
Associating a Shader to a Sprite
Sprite API has a new call to deal with that: Sprite:setShader(shader) tells Gideros to use the specified shader for rendering the sprite. Setting back the shader to nil actually revert to the default shader.