coolray.org FAQ Contact Us
CoolRay Banner
CoolRay / Documentation
PreviousUpNext

6. Tutorial

This tutorial will show in the first section how to use the basic features of the CoolRay Language. In the second section,

Basics

In this chapter we will learn how to create a simple Scene.

The CoolRay Language is object oriented. The language distinguishes between classes and objects. A object is an instance of its class. E.g. if we want to instanciate a object of the class sphere, we write the class name followed by a block. A block is marked with curly brackets, and may have zero, one or more objects, or property assignments inside.

Coordinate System

In order to position our objects, we have to use 3D coordinates. The coordinate system CoolRay uses, is a so called left-handed coordinate system. This type of coordinate system is often used by 3D graphic programs. The positive x-axis points left, the positive y-axis points up and the z-axis points off.

CoolRay's Coordinate System

If we want to specify a point in the 3D space, we use a vector constant. A vector constant is written as <x, y, z>. The center would be <0, 0, 0> and <0, 1, 0> would be one unit above the origin.

Hello World

The easiest possible scene consists of a camera only. This is not very usefull as there is no object to render:

scene HelloWorld1;
Scene {
  PerspectiveCamera {    
    location := <0, 0, -5>;
  }
  World {}
}
Example 1: HelloWorld1 and how it looks like

The first element of this scene is the scene name.

This is followed by the scene block.

Inside the Scene Block there is one Camera and one World object. The camera is located 5 units "behind" the origin and looks towards the origin. All solids in the World Block can be visible to the Camera. A solid is a three dimensional geometric object.

An example of a solid is the sphere. Now we want to have a sphere in our world.

scene HelloWorld2;
Scene {
  PerspectiveCamera {    
    location := <0, 0, -5>;
  }
  World {
  
    Sphere {
    }
  
  }
}
Example 2: HelloWorld2 and how it looks like

We just added a new object of the sphere to the world. This was done by writing the Class name (Sphere) followed by an empty block inside the World's block.

If you try to render this, the image would be black, as there is no light source defined. If we add a pointlight we get our first image.

scene HelloWorld;

Scene {
  PerspectiveCamera {    
    location := <0, 0, -5>; 
  }
  World {
    PointLight {      
      location := <-10, 10, -10>;
    }
    
    Sphere {
      SimpleTexture{} // to be removed
    }
  }
}
Example 3: HelloWorld and how it looks like

The light source is located 10 units left, 10 units above and 10 units behind the origin.

Applying Values To Properties

Every Object may have properties. Applying new values to properties changes the object's attributes.

If we want a smaller sphere, we can apply a different radius to it.

scene HelloWorld;

Scene {
  PerspectiveCamera {    
    location := <0, 0, -5>; // to be removed
    look_at := <0, 0, 0>; // to be removed
  }
  World {
    PointLight {      
      location := <-10, 10, -10>; // to be removed
    }
    
    Sphere {
      radius := 0.5;
      SimpleTexture{} // to be removed
    }
  }
}
Example 4: HelloWorldSmall and how it looks like

The properties have a predefined value. See the Object Reference for details.

Using Object References

Sometimes it is usefull to have a reference to a object. It is possible to share this object through a reference.

In the following example we declare a object reference with the keyword "var", the reference name (myLight) and the type of the reference (PointLight).

We can assign this reference to a property, which is of the same type or one of the base classes.

if we want to modify properties of the referred object, we can use the dot-operator. In the example below, the light source was initially on the left side. But later on it was overwritten by using the dot-operator. The light source is now on the right side.

scene HelloWorld;

Scene {
  PerspectiveCamera {    
    location := <0, 0, -5>; // to be removed
    look_at := <0, 0, 0>; // to be removed
  }
  World {
    var myLight : PointLight;
    
    myLight := PointLight {
      location := <-10, 10, -10>;
    }

    _lights := myLight;

    myLight.location := <10, 10, -10>;

    Sphere {
      SimpleTexture{} // to be removed
    }
  }
}
Example 5: RefDemo and how it looks like

Adding more Objects

If we want to have more than one sphere in our world, no problem: just add them to the world's block.

As we don't want to have them on the same position we apply different centers to them:

scene HelloWorld;

Scene {
  PerspectiveCamera {    
    location := <0, 0, -5>;
    look_at := <0, 0, 0>;
  }
  World {
    PointLight {      
      location := <-10, 10, -10>;
    }
    
    Sphere {
      center := <-1, -1, 0>;
      radius := 0.5;
    }
    Sphere {
      center := <1, -1, 0>;
      radius := 0.5;
    }
    Sphere {
      center := <-1, 1, 0>;
      radius := 0.5;
    }
    Sphere {
      center := <1, 1, 0>;
      radius := 0.5;
    }
  }
}
Example 6: HelloWorldQuad and how it looks like

This gives four spheres.

Textures

If we want to change the object's appearance, we have to add a texture object to its block. The texture object may contain one Pigment and one Finish Object.

Simple Pigment

The pigment describes the color of the object. The simpliest pigment object is the SolidColorPigment. It has only a color property. The hole object is tinted with this color.
scene HelloWorld;

Scene {
  PerspectiveCamera {    
    location := <0, 0, -5>;
    look_at := <0, 0, 0>;
  }
  World {

    PointLight {      
      location := <-10, 10, -10>;
    }
    Sphere {

      SimpleTexture {
        SolidColorPigment {
          color :=  rgb <0.7, 0.7, 1>;
        }
      }

    }
  }
}
Example 7: BlueSphere and how it looks like

Algorithmic Pigments

As uni-colored objects are a little bit boaring, we want to have objects made from wood, stone. This is what the XYZPigment is for. We can define a Pattern that describes how the colors are distributed and to which colors the pattern maches to. This is done by including a Pattern and a Colormap object to the XYZPigment.

The following example uses the CheckerPattern to define the tiles and a SimpleColorMap where we can define two colors. The result is a black and white tiled floor.

Note: we have to lower the floor a little bit in order to cut the pattern not at its border (which would look not as expected).

scene TiledFloor;

Scene {
  PerspectiveCamera {    
    location := <0, 2, -10>;
    look_at := <0, 0, 0>;
    angle := 45;
  }
  World {

    PointLight {      
      location := <0, 5, 0>;
      fade_power := 2;
      fade_distance := 7;
    }

    Plane { 
      normal := <0, 1, 0>;
      distance := -0.001;

      SimpleTexture {
        XYZPigment {
          CheckerPattern {
            size := 2;
          }
          SimpleColorMap {
            color1 :=  rgb <1, 1, 1>;
            color2 :=  rgb <0.15, 0.15, 0.15>;
          }
        }
      }

    }
  }
}
Example 8: TiledFloor and how it looks like
scene Wood;

Scene {

  PerspectiveCamera {
    location := <0, 3, -5>;
    look_at := <0,0.5,2>;
  }

  World {

    PointLight { 
      location := <-5, 5, -5>;
    }

    Box { 
      point1 := <-2,-0.5,0>;
      point2 := <2,0.5,15>;

      SimpleTexture {
	XYZPigment {
          WoodPattern {
            noise := 0.2;
            turbulence := 0;
            octaves := 1;
            xturbulence := 0;
            yturbulence := 0;
            zperturbation := 0.9;
            zfrequency := 2;
            zoffset := 0;
            znoise := 0.7;
	    Scale {
	      scale := <0.2,0.2,4>;
	    }
          }
          ColorMapList {
            ColorMapListEntry { value := 0; color :=  rgb <0.7, 0.5, 0>; }
            ColorMapListEntry { value := 0.2; color :=  rgb <0.5, 0.3, 0>; }
            ColorMapListEntry { value := 0.8; color :=  rgb <0.7, 0.5, 0>; }
            ColorMapListEntry { value := 1; color :=  rgb <0.7, 0.5, 0>; }
          }
	}
	Finish {
          ambient := 0.2;
          diffuse := 0.9;
	}
      }
    }
  }
}
Example 9: Wood and how it looks like

Finish

Additional to the pigment of an object we can adjust the material. This is done with the Finish object.

Smooth polished objects reflect light in the same angle it came in. The Reflection property adjusts the amount of reflected rays. If set to 1, light is totally reflected at the surface.

The color of the reflected light is usually filtered by metallic objects. To simulate this, we can set the value of the property metallic to 1. The mirrored floor in the example below gets filtered red at the right sphere.

scene MirrorSphere;

Scene {
  PerspectiveCamera {    
    location := <0, 3, -5>;
    look_at := <0, 1, 0>;
    angle := 45;
  }
  World {

    var metalFinish :Finish;
    var plasticFinish :Finish;
    var c2: Color;
    
    c2 := rgb <1, 0.7, 0.7>;

    metalFinish := Finish {
      reflection := 0.75;
      metallic := 1;
    }

    plasticFinish := Finish {
      reflection := 0.75;
      metallic := 0;
    }

    PointLight {      
      location := <0, 5, 0>;
      fade_power := 2;
      fade_distance := 7;
    }

    Sphere { 
      center := <-1, 1, 0>;

      SimpleTexture {
        SolidColorPigment {
          color := c2;
        }
        finish := plasticFinish;
      }
    }

    Sphere { 
      center := <1, 1, 0>;

      SimpleTexture {
        SolidColorPigment {
          color := c2;
        }
        finish := metalFinish;
      }
    }

    Plane { 
      normal := <0, 1, 0>;
      distance := -0.001;

      SimpleTexture {
        XYZPigment {
          CheckerPattern {
            size := 2;
          }
          SimpleColorMap {
            color1 :=  rgb <1, 1, 1>;
            color2 :=  rgb <0.15, 0.15, 0.15>;
          }
        }
      }

    }
  }
}
Example 10: MirrorSphere and how it looks like

If we want to have a translucent object, we have to adjust the properties refraction and ior (index of refraction).

Ior controls how much the light is bent when it travels through the object's surface. Some examples: diamond 2.42, glass 1.45, water 1.33, ice 1.31, air 1.00

scene GlassSphere;

Scene {
  PerspectiveCamera {    
    location := <0, 3, -5>;
    look_at := <0, 1, 0>;
    angle := 45;
  }
  World {

    var glassFinish :Finish;
    var c2: Color;
    
    c2 := rgbt <1, 1, 1, 0.95>;

    glassFinish := Finish {
      refraction := 1.0;
      ior := 1.5;
    }

    PointLight {      
      location := <0, 5, 0>;
      fade_power := 2;
      fade_distance := 7;
    }

    Sphere { 
      center := <0, 1, 0>;

      SimpleTexture {
        SolidColorPigment {
          color := c2;
        }
        finish := glassFinish;
      }
    }

    Plane { 
      normal := <0, 1, 0>;
      distance := -0.001;

      SimpleTexture {
        XYZPigment {
          CheckerPattern {
            size := 2;
          }
          SimpleColorMap {
            color1 :=  rgb <1, 1, 1>;
            color2 :=  rgb <0.15, 0.15, 0.15>;
          }
        }
      }

    }
  }
}
Example 11: GlassSphere and how it looks like

Loop- and Conditional-Statements

A very strong feature of CoolRay is the possibility to use loops and conditional statements. It is possible to create several objects with a loops.

The For Loop

Constructive Solid Geometric (CSG)

CSG is used to create complex objects out if simple basic objects.

Union

scene CSGUnion;

Scene {
  PerspectiveCamera {    
    location := <1, 3, -5>;
    angle := 45;
  }
  World {
    var glassFinish :Finish;
    var c1: Color;
    var c2: Color;
    
    background_color := rgb <1, 1, 1>;
    
    c1 := rgbt <1, 0.5, 0.5, 0.5>;
    c2 := rgbt <0.5, 0.5, 1, 0.5>;

    PointLight {      
      location := <0, 5, 0>;
      fade_power := 2;
      fade_distance := 7;
    }

    Union {
      Sphere { 
	center := <-0.5, -0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c1;
          }
	}
      }
      Sphere { 
	center := <0.5, 0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c2;
          }
	}
      }
    }

  }
}
Example 12: CSGUnion and how it looks like

Merge

scene CSGMerge;

Scene {
  PerspectiveCamera {    
    location := <1, 3, -5>;
    angle := 45;
  }
  World {
    var glassFinish :Finish;
    var c1: Color;
    var c2: Color;
    
    background_color := rgb <1, 1, 1>;
    
    c1 := rgbt <1, 0.5, 0.5, 0.5>;
    c2 := rgbt <0.5, 0.5, 1, 0.5>;

    PointLight {      
      location := <0, 5, 0>;
      fade_power := 2;
      fade_distance := 7;
    }

    Merge {
      Sphere { 
	center := <-0.5, -0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c1;
          }
	}
      }
      Sphere { 
	center := <0.5, 0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c2;
          }
	}
      }
    }

  }
}
Example 13: CSGMerge and how it looks like

Difference

scene CSGDifference;

Scene {
  PerspectiveCamera {    
    location := <1, 3, -5>;
    angle := 45;
  }
  World {
    var glassFinish :Finish;
    var c1: Color;
    var c2: Color;
    
    background_color := rgb <1, 1, 1>;
    
    c1 := rgbt <1, 0.5, 0.5, 0.5>;
    c2 := rgbt <0.5, 0.5, 1, 0.5>;

    PointLight {      
      location := <0, 5, 0>;
      fade_power := 2;
      fade_distance := 7;
    }

    Difference {
      Sphere { 
	center := <-0.5, -0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c1;
          }
	}
      }
      Sphere { 
	center := <0.5, 0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c2;
          }
	}
      }
    }

  }
}
Example 14: CSGDifference and how it looks like

Intersection

scene CSGIntersect;

Scene {
  PerspectiveCamera {    
    location := <1, 3, -5>;
    angle := 45;
  }
  World {
    var glassFinish :Finish;
    var c1: Color;
    var c2: Color;
    
    background_color := rgb <1, 1, 1>;
    
    c1 := rgbt <1, 0.5, 0.5, 0.5>;
    c2 := rgbt <0.5, 0.5, 1, 0.5>;

    PointLight {      
      location := <0, 5, 0>;
      fade_power := 2;
      fade_distance := 7;
    }

    Intersect {
      Sphere { 
	center := <-0.5, -0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c1;
          }
	}
      }
      Sphere { 
	center := <0.5, 0, 0>;

	SimpleTexture {
          SolidColorPigment {
            color := c2;
          }
	}
      }
    }

  }
}
Example 15: CSGIntersect and how it looks like

PreviousUpNext
You are visitor No.

counter

Copyright (c) 2001 Stefan Michel, All Rights Reserved.
Last modified: