RenderStack 11.06.1

RenderStack is a set of C# assemblies that make it easier to use OpenGL 3. Documentation is non-existent - use the source. RenderStack uses OpenTK.

Current RenderStack features

RenderStack 11.10 preview

Modeling.png

Coming soon.

Download

renderstack-11.06.3.zip source archive, June 21, 2011

License

RenderStack is licensed with the MIT / X11 license. Copyright (c) 2011 Timo Suoranta.

Examples

Currently there are following examples.

Simple

This is a minimal application using RenderStack. It renders a sphere on screen.

//  Copyright (C) 2011 by Timo Suoranta                                            
//                                                                                 
//  Permission is hereby granted, free of charge, to any person obtaining a copy   
//  of this software and associated documentation files (the "Software"), to deal  
//  in the Software without restriction, including without limitation the rights   
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      
//  copies of the Software, and to permit persons to whom the Software is          
//  furnished to do so, subject to the following conditions:                       
//                                                                                 
//  The above copyright notice and this permission notice shall be included in     
//  all copies or substantial portions of the Software.                            
//                                                                                 
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN      
//  THE SOFTWARE.                                                                  

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

using RenderStack.Geometry;
using RenderStack.Geometry.Shapes;
using RenderStack.Graphics;
using RenderStack.Math;
using RenderStack.Mesh;
using RenderStack.Scene;

using Matrix4 = RenderStack.Math.Matrix4;
using Vector3 = RenderStack.Math.Vector3;

namespace example.Simple
{
    public class Application : GameWindow
    {
        //  The region below is for backwards compatibility only
        #region shaders120
        string vs120 = 
@"#version 120                                                          
                                                                        
attribute vec3 _position;                                               
attribute vec3 _normal;                                                 
                                                                        
uniform mat4 _model_to_clip_matrix;                                     
uniform mat4 _model_to_world_matrix;                                    
                                                                        
varying vec3 v_normal;                                                  
                                                                        
void main()                                                             
{                                                                       
    gl_Position = _model_to_clip_matrix * vec4(_position, 1.0);         
    v_normal    = vec3(_model_to_world_matrix * vec4(_normal, 0.0));    
}                                                                       ";

        string fs120 = 
@"#version 120                                                          
                                                                        
uniform vec3  _light_direction;                                         
uniform vec3  _light_color;                                             
uniform vec3  _surface_color;                                           
                                                                        
varying vec3 v_normal;                                                  
                                                                        
void main(void)                                                         
{                                                                       
    vec3  N              = normalize(v_normal);                         
    vec3  L              = _light_direction.xyz;                        
    float ln             = dot(L, N);                                   
    float lnClamped      = max(ln, 0.0);                                
    vec3  linearRadiance = _surface_color * _light_color * lnClamped;   
    gl_FragData[0].rgb = pow(linearRadiance, vec3(1.0/2.2));            
    gl_FragData[0].a   = 1.0;                                           
}                                                                       ";
        #endregion shaders120
        //  Forward compatible contexts must use newer GLSL version
        #region shaders330
        string vs330 = 
@"#version 330                                                          
                                                                        
in vec3 _position;                                                      
in vec3 _normal;                                                        
                                                                        
out vec3 v_normal;                                                      
                                                                        
uniform mat4 _model_to_clip_matrix;                                     
uniform mat4 _model_to_world_matrix;                                    
                                                                        
void main()                                                             
{                                                                       
    gl_Position = _model_to_clip_matrix * vec4(_position, 1.0);         
    v_normal    = vec3(_model_to_world_matrix * vec4(_normal, 0.0));    
}                                                                       ";

        string fs330 = 
@"#version 330                                                          
                                                                        
in vec3 v_normal;                                                       
                                                                        
out vec4 out_color;                                                     
                                                                        
uniform vec3  _light_direction;                                         
uniform vec3  _light_color;                                             
uniform vec3  _surface_color;                                           
                                                                        
void main(void)                                                         
{                                                                       
    vec3  N              = normalize(v_normal);                         
    vec3  L              = _light_direction.xyz;                        
    float ln             = dot(L, N);                                   
    float lnClamped      = max(ln, 0.0);                                
    vec3  linearRadiance = _surface_color * _light_color * lnClamped;   
    out_color.rgb = pow(linearRadiance, vec3(1.0/2.2));                 
    out_color.a   = 1.0;                                                
}                                                                       ";
        #endregion shaders330

        Mesh        mesh;
        Program     program;
        Viewport    viewport;
        MeshMode    meshMode = MeshMode.PolygonFill;

        Camera                              camera              = new Camera();
        Frame                               modelFrame          = new Frame();
        Dictionary<string, IUniformValue>   parameters          = new Dictionary<string,IUniformValue>();
        AttributeMappings                   attributeMappings   = new AttributeMappings();

        public Application(OpenTK.DisplayDevice display)
        :   base(
            640, 
            480,
            new GraphicsMode(), 
            "RenderStack", 
            0,
            display, 
            2, 1, GraphicsContextFlags.Default
            //  In releases, ask for 3.3 only if you really need it.
            //  Test forward compatible during development, but never ship with it set
            //3, 3, GraphicsContextFlags.ForwardCompatible
        )
        {
        }

        protected override void OnLoad(System.EventArgs e)
        {
            //  Check GL version and feature capabilities
            RenderStack.Graphics.Configuration.Initialize();

            Geometry geometry = new Sphere(2.00f, 20, 20);
            //  You can try different shapes:
            //  Geometry geometry = new RenderStack.Geometry.Shapes.Icosahedron(1.0f);
            mesh = new GeometryMesh(geometry, NormalStyle.PointNormals).GetMesh;

            viewport = new Viewport(base.Width, base.Height);

            modelFrame.LocalToParent.Set(
                Matrix4.CreateTranslation(0.0f, 0.0f, 0.0f)
            );

            camera.Frame.LocalToParent.Set(
                Matrix4.CreateLookAt(
                    new Vector3(0.0f, 0.0f, -4.0f),     //  camera location
                    new Vector3(0.0f, 0.0f,  0.0f),     //  aim point
                    new Vector3(0.0f, 1.0f,  0.0f)      //  up vector
                )
            );

            camera.FovYRadians      = RenderStack.Math.Conversions.DegreesToRadians(60.0f);
            camera.ProjectionType   = ProjectionType.PerspectiveVertical;

            attributeMappings.Add("_position", VertexUsage.Position, 0, 3);
            attributeMappings.Add("_normal",   VertexUsage.Normal,   0, 3);

            /*                   name in shader            uniform  */ 
            UniformMappings.Add("_model_to_world_matrix",  LogicalUniform.ModelToWorld);
            UniformMappings.Add("_world_to_model_matrix",  LogicalUniform.WorldToModel);
            UniformMappings.Add("_model_to_clip_matrix",   LogicalUniform.ModelToClip);
            UniformMappings.Add("_clip_to_model_matrix",   LogicalUniform.ClipToModel);
            UniformMappings.Add("_world_to_clip_matrix",   LogicalUniform.WorldToClip);
            UniformMappings.Add("_clip_to_world_matrix",   LogicalUniform.ClipToWorld);
            UniformMappings.Add("_view_position_in_world", LogicalUniform.ViewPositionInWorld);

            /*                  type     name in shader      parameter name   */ 
            UniformMappings.Add<Floats>("_light_direction", "light_direction");
            UniformMappings.Add<Floats>("_light_color",     "light_color"    );
            UniformMappings.Add<Floats>("_surface_color",   "surface_color"  );

            parameters["surface_color"]     = new Floats(1.0f, 1.0f, 1.0f);
            parameters["light_direction"]   = new Floats(0.0f, 1.0f, 0.0f);
            parameters["light_color"]       = new Floats(1.0f, 1.0f, 1.0f);

            if(RenderStack.Graphics.Configuration.glslVersion >= 330)
            {
                program = new Program(vs330, fs330);
            }
            else
            {
                program = new Program(vs120, fs120);
            }

            program.AttributeMappings = attributeMappings;

            program.Bind(camera);
            program.Bind(parameters);

            //  Setup initial GL state
            {
                //  Since we only use one program, we don't
                //  need to touch this after.
                camera.UpdateCameraFrame();
                camera.UpdateViewport(viewport);
                camera.UpdateModelFrame(modelFrame);
                program.Use();
                program.ApplyUniforms();

                GL.Enable(EnableCap.DepthTest);
                GL.Enable(EnableCap.CullFace);

                float gammaHalf = (float)Math.Pow(0.5, 1.0 / 2.2);
                GL.ClearColor(gammaHalf, gammaHalf, gammaHalf, 1.0f);
                GL.Clear(ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
                SwapBuffers();
                Visible = true;

                //  Since we only use one mesh, we don't 
                //  need to change this after
                mesh.ApplyAttributes(program, meshMode);
            }

            Resize += new EventHandler<EventArgs>(Application_Resize);
            Unload += new EventHandler<EventArgs>(Application_Unload);
        }

        void Application_Unload(object sender, EventArgs e)
        {
            if(mesh != null)
            {
                mesh.Dispose();
                mesh = null;
            }
            if(program != null)
            {
                program.Dispose();
                program = null;
            }
        }

        void Application_Resize(object sender, EventArgs e)
        {
            //  When window size is changed, we need to update
            //  GL viewport and projection matrix and any
            //  other matrices that depend on it.
            viewport.Resize(this.Width, this.Height);

            GL.Viewport(
                (int)viewport.X, 
                (int)viewport.Y, 
                (int)viewport.Width, 
                (int)viewport.Height
            );
            camera.UpdateViewport(viewport);
            camera.UpdateModelFrame(modelFrame);

            //  Is is also necessary to upload changed uniforms
            program.ApplyUniforms();
        }

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            if(Keyboard[OpenTK.Input.Key.Escape])
            {
                Exit();
            }
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);

            GL.DrawElements(
                mesh.IndexBuffer(meshMode).BeginMode,
                (int)(mesh.IndexBuffer(meshMode).Count),
                mesh.IndexBuffer(meshMode).DrawElementsType,
                0
            );

            SwapBuffers();
        }

        [STAThread]
        public static void Main()
        {
            OpenTK.DisplayDevice chosenDisplay = OpenTK.DisplayDevice.Default;

            using (var application = new Application(chosenDisplay))
            {
                application.Title = "example.Simple";

                application.Run(30);
            }
        }
    }
}

RenderToTexture

This is the simple example modified to render the sphere to a texture and then render a quad with that texture.

Scene

This is an example how to render multiple objects in a scene.

UI

ui.png

This is the scene example with added simple user interface. Only few of the user interface components actually work.

Warning:
The OpenTK version included is a snapshot of OpenTK subversion 16th June 2011. Sometimes it may not work as expected, you may need to get latest OpenTK from subversion and build it using OpenTK solution, and replace project reference with a reference to OpenTK.dll.