Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more

Tech

Shaders Overview - Part 4

Posted by Mike Dailly on 28 June 2013

In this section I'm going to discuss the new vertex format creation tool, the new vertex builder, and what this means for how you can use shaders. First, why do we need to be able to define our own vertex formats? Well, currently Studio uses 2 formats, one for simple 2D stuff like sprites, and 1 for when we're doing 3D which includes normals. These are fine for the most part, but are limiting if your trying to use through a special effect. For example, what if you wanted to also pass in an object ID to render if you pressed a key, and you were going to use a single shader constant to toggle this on/off? Well, you would probably have to pack it into the colour or normal values, but that's not only annoying, but again, limiting.

So what we've done is to give you the full scope and power of shaders, allowing you to do anything by creating your own format. This means you would have to build every primitive yourself, but at least you can do it. First, lets take a look at the format API.

vertex_format_begin()
vertex_format_end()
vertex_format_add_position()
vertex_format_add_position_3d()
vertex_format_add_colour()
vertex_format_add_normal()
vertex_format_add_textcoord()
vertex_format_add_custom()

Now, for the most part, you'll be adding positions, colours, and "lots" of texture coordinates, but when it gets "sticky" the custome api call will let you define anything. I won't go into API specifics (paramaters etc), but will show you an example. In this example, we create the 2D Studio format that we can then use to either build our own data, or let Studio draw to. Note: Studio won't use this format, but as the underlying data is the same, it'll map over just fine.

vertex_format_begin();
vertex_format_add_position_3d();
vertex_format_add_colour();
vertex_format_add_textcoord();
global.my_format = vertex_format_end();

After you finish creating the format, it'll return a handle that you can then use later for creating actual vertex data. Notice you can't destroy them. Since these are bound to shaders, and shaders are static things, it seems logical you will always need the format of a shader you've written lying around somewhere.

Using this API, you can add extra texture coordinates, more colours or information about bones etc. for animation. In the past to create vertex data you would use d3d_model_vertex_????() function set, but this is limited to a specific format. So for this new user format, we have another new API.

vertex_create_buffer()
vertex_create_buffer_ext()
vertex_begin()
vertex_end()
vertex_position()
vertex_position_3d()
vertex_colour()
vertex_rgba();
vertex_texcoord()
vertex_normal()
vertex_float1()
vertex_float2()
vertex_float3()
vertex_float4()
vertex_ubyte4() vertex_freeze() vertex_submit() vertex_delete()

Again, I won't get into an API/paramater discussion here, you'll get that in the manual later, but by seperating the elements out, it allows the building of any format you'd care to create. Here's an example of it in use.

    // get the vertex builder we're going to use.
var b = global.vbuff;
vertex_begin(b,global.my_format);

// 1st triangle....
vertex_position_3d(b,10,10,1);
vertex_colour(b,c_white,1);
vertex_texcoord(b, 0,0);

vertex_position_3d(b,110,10,1);
vertex_colour(b,c_white,1);
vertex_texcoord(b, 1,0);

vertex_position_3d(b,110,110,1);
vertex_colour(b,c_white,1);
vertex_texcoord(b, 1,1);


// 2nd triangle....
vertex_position_3d(b,110,110,1);
vertex_colour(b,c_white,1);
vertex_texcoord(b, 1,1);

vertex_position_3d(b,10,110,1);
vertex_colour(b,c_white,1);
vertex_texcoord(b, 0,1);

vertex_position_3d(b,10,10,1);
vertex_colour(b,c_white,1);
vertex_texcoord(b, 0,0);

vertex_end(b);

var tex = background_get_texture(background1);
vertex_submit( b, pr_trianglelist, tex );

So you simply fill out each vertex - making sure each vertex is complete before  moving onto the next, and then at the end, you submit it.  The buffer will hold anything you write until you do a vertex_begin() on it again, meaning you can do semi-dynamic stuff if you want to. The API will enforce the format you've selected and insist you finish the current vertex before moving on so should help keep errors to a minimum.

We will be adding more command later - like copying to and from other buffers, which in turn will allow you to load from files etc. and should make proper model loading much easier. These commands should also be pretty quick, certainly quick enough for doing dynamic stuff, and we may in the future streamline final builds to remove API validation making them quicker still.

Using your own vertex format together with a custom shader should give you everything you need to be able to do - well, anything! It enables you to add extra information into the vertex stream, so you can identify which spriite, or even which corner of a sprite your dealing with. This in turn can then be used to do things like outline rendering, drop shadows, glow and so on. Full shader based animation systems should now be possible, as would displacement mapping for a 2.5D game, but even something as simple as an extra value for palette selection would also be very possible.

In the next part, we'll look at the constants Studio will setup for you, and how you access and use them.

 

Back to Top