Don’t worry if you don’t understand how to use input layouts and vertex buffers etc, because while it’s the fastest and most customizable way to do rendering in Frontend, it’s also the most low level and inconvenient way. Frontend Utils offers a much easyer way to do rendering, which might look familiar for people used to rendering using the glBegin and glEnd-method.
The first part looks familiar as always, but notice that we also include Frontend2Utils.h.

#include <stdio.h>
#include <OpenFrontend2.h>
#include <Frontend2Utils.h>

using namespace Frontend;
using namespace Frontend::Graphics;

int main(int argc, char* argv[])
{
    Window* window = CreatePlatformWindow(800, 600, "Hello World", false);
    Device* device = CreateDeviceGL2CG(window, DepthStencilFormatD24S8, 0, 0);

The first thing we need to do is to create a GeoStream object for what we want to draw. This should be done load-time (not inside a rendering loop).

   Utils::GeoStream gs(device, 3);

device is a pointer to our frontend device and 3 is the maximum amount of vertices we’ll draw.

As always, there has to be a shader program running on the device in order to get something on to the screen. In this lesson we won’t go in depth about shader pogramming, but here’s a basic Cg-program source file that will do:

struct VSInput
{
    float4 Position: POSITION;
    float4 Color: COLOR;
};  

struct VSOutput
{
    float4 Position: POSITION;
    float4 Color: COLOR;
};  

VSOutput vsMain(VSInput Input)
{
    VSOutput Output;
    Output.Position = Input.Position;
    Output.Color = Input.Color;
    return Output;
}  

float4 psMain(VSOutput Output): COLOR
{
    return Output.Color;
}

Note: When using GeoStream, the positions will be mapped to the POSITION attributes, the colors will be mapped to the COLOR attributes, the normals will be mapped to the NORMAL attributes, and the texcoords will be mapped to the TEXCOORD0 attributes.

Make a directory called Data in the same directory as your executable and save the shader as shader.cg.

In order to load files, we need a proxy object. We make our proxy read it’s files from the Data directory. You’ll learn more about the proxy object later on.

Utils::Directory* folder = new Utils::Directory("Data/");
Utils::Assets::Proxy* proxy = new Utils::Assets::Proxy(folder, device);

We load our Cg program using Frontend Utils’ shader loader:

   Program* program = proxy->GetProgram("shader.cg;shader.cg");

Then, within our rendering loop, we can bind our shader program and draw using functions similar to the glBegin and glEnd-method.

    while (device->Update())
    {
        device->Clear(ClearBuffersColor, 0, 0, 0, 1, 1, 0);
        device->SetProgram(program);

        gs.Begin(PrimitiveTypeTriangles); // start drawing triangles
            gs.Color(1.0f,0.0f,0.0f);
            gs.Position(-1.0f,-1.0f, 0.0f);  // The first vertex

            gs.Color(0.0f,1.0f,0.0f);
            gs.Position( 1.0f,-1.0f, 0.0f); // The second vertex

            gs.Color(0.0f,0.0f,1.0f);
            gs.Position( 0.0f, 1.0f, 0.0f);  // The third vertex
        gs.End();
    }

    return 0;
}

Wow, that was almost too easy!

Note: Color() and Texcoord() should be called before Position() for each vertex.

Optimizing hints

A neat thing to note is that once if you have drawn something using a GeoStream, the GeoStream remembers the geometry. So if you want to draw the exact same geometry again later, you can use the Redraw() function. This will be significantly faster than entering all the data again between begin/end.

gs.Redraw();

If you are just going to draw static geometry, you can move the Begin()/End() sequence outside the rendering loop and just use Redraw() inside the rendering loop. This will speed things up as the data doesn’t need to be sent to the graphics memory every frame.




FireStats icon Powered by FireStats