PolyCube is a web-based programming environment that lets your write small computer graphics oriented, interactive toys in RiceScript - a simple programming language with a C-like syntax that can be easily translated to Javascript or GLSL.

The primary design goal of PolyCube is to be backwards compatible with EvalDraw and PolyDraw, popular fast prototyping environments. Usually, you can just copy and paste your existing EvalDraw/PolyDraw scripts and with no or minor changes they should compile and run the same way in PolyCube. (*)
* Check out the language specification below to find out the differences.

It is also similar in spirit to WebGLPlayground, however, in order to make WebGLPlayground scripts work in PolyCube, the @main section has to be ported from Javascript to RiceScript.

Additionally, PolyCube is introducing its own features and extensions, for example you can draw 2d graphics (using EvalDraw library) on top of full screen fragment shader. Another interesting (still in experimental stage) feature is #use macro - an extension to GLSL language that let's you use built-in constants/functions or maintain common code (with restrictions) between GLSL and RiceScript.

PolyCube/RiceScript is under continuous development and bug fixing, please check out release_notes.txt for updates.

If you want to quickly start with PolyCube, be sure to check out PolyCube Tutorial.
Reference Documentation

Below you can find full documentation of PolyCube framework, including script structure and standard library.

All function names in standard library are declared in both mixedCase and lowercase style (for PolyDraw/EvalDraw compatibility).


Script structure

Every script starts with RiceScript rendering logic followed by list of vertex and fragment shaders:
// RiceScript section always starts at the begining

()
{
  // RiceScript main function
}

// Custom function declaration
@v:firstShader // Vertex shader with optional name = "firstShader" // GLSL-code for vertex shader void main() { gl_Position = /* here calculate vertex position in clipping space */ ; } @f:firstShader // Fragment shader // GLSL-code for fragment shader void main() { gl_FragColor = /* here calculate fragment color */ ; } @v:secondShader // ... @f:secondShader // ... // More fragment and vertex shaders possible
Note, that a program (set using glSetShader, see below) can contain vertex and fragment shaders with different names. Therefore, it is possible to combine for example "firstShader" vertex shader and "secondShader" fragment shader.
Optionally, shaders can be declared without a name (just @v or @f). In this case, they can be still set by index (in order of definition starting from 0).

Additionally, you can defined "common" sections that can be injected to both fragment and vertex shaders code using #use macro.
For example:
// RiceScript section
()
{
   // ...
}

@v:myCommonSection

// GLSL-code for both vertex and fragment shader

@v:myShader

#use :myCommonSection

// GLSL-code for vertex shader

void main()
{
  gl_Position = /* ... */;
}

@f:myShader

#use :myCommonSection

// GLSL-code for fragment shader

void main()
{
  gl_FragColor = /* ... */;
}

// ...
  

Macro reference

You can use following macros to set various environment options:
#option auto_clear 1 or 0
If set to 1, automatically clears 3d rendering canvas: depth, color and stencil; default value is 1;
#option opaque_canvas 1 or 0
If set to 1, 3d rendering canvas alpha value is ignored; default value is 1
#option preserve_buffer 1 or 0
This option is for optimization purposes only; by default it is set to 1 and equivalent to WebGL preserveDrawingBuffer:true; if set to 0, thumbnail feature doesn't work and buffer is automatically cleared (irrespective of auto_clear setting)
#option antialias 1 or 0
Toggle full-screen antialiasing; default value is 1

Additionally, you can #use macro to integrate RiceScript and GLSL-code or to use common GLSL sections:
#use glsl_math
Declare in RiceScript section to enable GLSL-like math and structures (see library reference below)
#use noise
Declare in fragment shader to enable built-in Perlin noise functions
#use myFunction
Declare in fragment or vertex shader to translate myFunction from RiceScript to GLSL (experimental feature, see language specification for more details)
#use :myCommonSection
Inject common GLSL code section into GLSL shader code


Template reference

Templates are pre-defined code libraries/frameworks that let's you create a simple program faster.

To use a template simply declare at the begining of your code:
#template templateName

Templates are written in RiceScript, therefore if you would like to extend functinality of your simple program, you can just copy, paste and modify template code instead of #template decleration.

Example templates:
(warning: template source code does not compile on its own)
#template plot
EvalDraw-style plotting program that plots anonymous (x) function.
Template's source code and example.
#template shader_plot_v1
EvalDraw-style plotting program that plots 2d function implemented in GLSL. Special uniforms:
float template_time; // current shader time in seconds
vec2 template_cursor; // position of mouse cursor in plot coordinates
int template_bstatus; // mouse button state (1=LMB, 2=RMB, 4=MMB)
Template's source code and example.
#template voxel
Evaluation and rendering of voxel equation in GLSL.
Template's source code and example.
#template volumetric_v1
Evaluation and rendering of distance fields in GLSL with physically-based materials. Distance field is precalculated and stored in a texture. This template optionally uses WEBGL2 features (with backwards compatibility to WebGL 1.0). Special uniforms:
float template_time; // current shader time in seconds
Template's source code and example.


Standard library reference

Functions that takes vector/matrix (vec2, vec3, vec4, mat2, mat3, mat4) as an argument or return type can be only called if macro #use glsl_math is declared.

PolyCube maintains a static pool of 256 textures and 256 meshes; functions that deal with meshes/textures just take mesh/texture index as an argument, no dynamic allocation is necessary. Mesh pool is empty by default. Texture pool is initialized with two default 128x128 textures:
texture 0 = checker board,
texture 1 = polka-dot.

By default, at the begining of every frame, first 4 textures from the pool are bound to first 4 texture units.

Following default uniforms are available in vertex or fragment shaders and shouldn't be explicitly declared:
uniform mat4 gl_ModelViewMatrix;
Model-view matrix; transformation from model to view space
uniform mat4 gl_ProjectionMatrix;
Projection matrix; transformation from view to clipping space
uniform mat4 gl_ModelViewMatrixInverse;
Inverse of model-view matrix
uniform mat3 gl_NormalMatrix;
Transpose of the inverse of 3x3 part of model-view matrix

Additionally, a helper function ftransform() is predefined in vertex shaders:
vec4 ftransform()
{
  return gl_ProjectionMatrix * ( gl_ModelViewMatrix * gl_Vertex );
}
  
If no vertex shader is declared a default one is used at index 0:
void main()
{
  gl_Position = ftransform();
}
  

WebGL 2.0 support

If WebGL 2.0 / GLSL ES 3.0 is available, macro WEBGL2 is predefined in GLSL shaders and WEBGL2 static variable in RiceScript section.

You can declare shader version explicity using #version macro:
   #version 100
   // or
   #version 300 es
However, shader version declaration is optional - if no version is declared, the highest available shader version is used and additional macros/helpers will be declared to make it easier to keep shader code cross-compatible.

If no version is declared and GLSL ES 3.0 is available:

#varying is predefined as out in vertex shaders and in in fragment shaders,

gl_FragColor is defined as default fragment shader output; otherwise, for GLSL 3.0 ES, shader output has to be declared using out keyword

both gl_FragDepthEXT and gl_FragDepth can be used interchangably

GL_EXT_frag_depth extension declaration is ignored; however, it can be still declared for GLSL 1.0 compatibility

Example of cross-compatible script:
()
{
   if (WEBGL2)
   {
     // do something WebGL 2 specific, i.e. render to 3d texture
   }
   else
   {
     // WebGL 1 fallback, i.e. render to 2d texture emulating 3d texture
   }
   glColor(.4,.6,1,1);
   glQuad(1);
}

@v: // vertex shader start
// no shader version declaration

varying vec4 color; // in GLSL ES 3.0 will be automatically out

void main()
{
  color = gl_Color;
  gl_Position = ftransform();
}

@f: // fragment shader start
// no shader version declaration

#extension GL_EXT_frag_depth : enable

varying vec4 color; // in GLSL ES 3.0 will be automatically in

void main()
{
#ifdef WEBGL2
  // Put GLSL ES 3.0 compatible shader code here
#else
  // GLSL 1.0 fallback
#endif
#ifdef GL_EXT_frag_depth
  gl_FragDepthEXT = .5; // in GLSL ES 3.0 will be replaced with gl_FragDepth 
#endif
  gl_FragColor = color;
}
  

And the same example for GLSL 3.0 ES without backwards compatibility:
()
{
   glColor(.4,.6,1,1);
   glQuad(1);
}

@v: // vertex shader start
#version 300 es

out vec4 color;

void main()
{
  color = gl_Color;
  gl_Position = ftransform();
}

@f: // fragment shader start
#version 300 es

in vec4 color;
out vec4 fragColor;

void main()
{
  gl_FragDepth = .5;
  fragColor = color;
}
  
Note: precision declaration is also optional, the default is highp.
As mentioned, we can also omit version declaration, as GLSL 3.0 ES will be automatically used if available.
Therefore, the final code without backwards compatibility can be written shorty as follows:
()
{
   glColor(.4,.6,1,1);
   glQuad(1);
}

@v: // vertex shader start
out vec4 color;

void main()
{
  color = gl_Color;
  gl_Position = ftransform();
}

@f: // fragment shader start
in vec4 color;

void main()
{
  gl_FragDepth = .5;
  gl_FragColor = color;
}
  


For more information about language syntax check out RiceScript specification.
Go back to main page.
Gallery     Docs     Tutorial     RiceScript    
Follow
   
Feedback
polycu.be (C) 2015
Sign out