Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Scavenger on Fri 14/03/2014 14:58:23

Title: Flat Shaded 3D models
Post by: Scavenger on Fri 14/03/2014 14:58:23
I've been working on elements for my game, and looking through demoscene stuff to get inspiration for some of the SFX I want to use to tell the story with. One of these things is flat shaded 3D models, which I have an affinity for - they look incredibly oldschool, and I do make 3D models as well as pixel art. I know flat shaded 3D prims are possible in AGS, the AGS3D module/plugin is testament to that. Unfortunately, that module/plugin only does 16/32bit, and my game is in 8-bit. Being 8-bit, it also brings up the problem that any shading can't rely on just RGB values. I've been thinking about this, and I think if I hardcode what tri is coloured what palette slot, I may be able to produce 3D images within the bounds of my game's limitations, like so:

(https://dl.dropboxusercontent.com/u/50882197/crit/3D_proposal.gif)
The black outline is so that the image can be seen even when the model is turned at an angle, since in this shading model, we wouldn't have the luxury of actual shading or lighting. But because of the lack of actual shading, I can also get away with using less polys for everything. I'd guess the flow would be like this:
1) Load OBJ model
2) Have an array the size of the number of tris in the model, with assigned colours to them
3) Draw the model using the assigned colours onto a full screen drawing surface.
4) Duplicate the drawing surface, have a completely black sprite, and cut out the model's dimensions with CopyTransparencyMask.
5) Draw the sillhouette 4 times, at offsets (0,-1),(0,1),(1,0),(-1,0) onto a new drawing surface
6) Draw the final sprite onto the drawing surface at offset (0,0).

But I'm not actually too up on the programming side of this (I'm an artist :<), and I can't find any old versions of the AGS3D module (the one that uses DrawTriangle) to test it out.

So, how easy would this be to do, and more importantly, would it be fast enough to run real time? I don't need any fancy texture mapping, or lighting, or even high polys, I just need to be able to rotate, scale, and position a model in 3D space. Where would I begin to do something like this?
Title: Re: Flat Shaded 3D models
Post by: abstauber on Fri 14/03/2014 16:23:12
Quoteand I can't find any old versions of the AGS3D module (the one that uses DrawTriangle) to test it out.
This one?
http://www.kweepa.com/step/ags/tech/Ags3d113.zip
Title: Re: Flat Shaded 3D models
Post by: Scavenger on Fri 14/03/2014 16:28:00
Ah, excellent! I'll try that one out!

Edit: Hmm, I don't think the non-plugin version can load obj files, it only makes primitives. I'll still see what I can glean from it, see if I can't make it run in 8bit.
Title: Re: Flat Shaded 3D models
Post by: Khris on Sun 16/03/2014 02:09:51
I had to try this and got this far (coded from scratch):

(http://i.imgur.com/U03x9Yz.png)

I didn't know about CopyTransparencyMask and it's working great!
Haven't tried it in 8bit yet though.

No clipping or z-sorting yet, but I implemented backface culling and that works perfectly for convex objects.
Title: Re: Flat Shaded 3D models
Post by: Scavenger on Sun 16/03/2014 07:58:03
Aaah, that's really awesome, Khris! That's exactly what I was talking about! I am always consistently amazed at the talent in these forums, ahaha.

How many polys do you think could be rendered like that without slowdown? Is it feasible for AGS to handle without choking on itself? I tested out just raw DrawTriangle commands once, and on my old laptop, I managed to get up to 2000/frame without it dropping below 60fps. But I'm guessing with the extra math involved for 3D, the reality would be a lot less. I'm pretty excited - I've made 3D models as a basis for my 2D work, but I've never used them realtime in a game before!

(And I guess 8bit would be trivial to do, so long as you have a palette and the ability to set colours to each tri.)
Title: Re: Flat Shaded 3D models
Post by: Khris on Sun 16/03/2014 13:34:18
I did try to optimize this from the start, for instance the position of vertices that are used by multiple triangles is only calculated once.
Right now, without any sorting, displaying 40 rotating cubes doesn't reduce the frame rate, but if I increase it to a mere 50, the FPS drop to 35; 60 cubes, 31.

With 40 cubes, I'm rotating 320 vertices and drawing ~240 tris, plus there's dynamic lighting and the backface culling, which means three dot products, vector length and ArcCos calculations times 480 tris.

60:
(http://i.imgur.com/vP1YtFi.png)
Title: Re: Flat Shaded 3D models
Post by: Calin Leafshade on Sun 16/03/2014 15:27:32
The calculation and the looping in the script is likely to be the bottleneck here. As a lua script you could probably get 10 times the performance.
Title: Re: Flat Shaded 3D models
Post by: Khris on Mon 17/03/2014 02:06:02
Yep, which would bring this guy right back to 40 FPS :)

(http://i.imgur.com/7AAEVHg.png)

Added z-sorting, importing obj files and fixed the lighting calculation (I had to rewrite it entirely, I'm surprised the first version gave decent results, given how completely off it was).
Title: Re: Flat Shaded 3D models
Post by: Scavenger on Mon 17/03/2014 20:49:31
I cannot believe this! I am absolutely astounded! Quite honestly I thought it would be an impossible task or a pipe dream, but there you go, doing it in mere days. Thank you so much!

In terms of colouring it in 8bit, I could whip up a simple CLUT generator that mixes together two or three shades of each colour in a range (in my game it would be 0-63), so you can approximate lighter and darker colours - it's not that difficult, I already have a more sophisticated version for translucency, making blends between black, a target colour, and white should be pretty trivial. How many shades are required for a suitable 3D effect? I'll whip something up.

Though, if you want to go real basic for lo colour 3D, you'd just need some way of painting the tris manually - I think that's how it worked in Alone In The Dark? (like this (http://regmedia.co.uk/2013/09/30/aitd_5.jpg)). No lighting, just coloured polygons. I remember Carnby's suit in particular having shading "drawn" onto it. Not the most fancy thing around, but suitable for what I want to use it for, at least, and it'll look like it has a texture on even though it's literally just coloured triangles!
Title: Re: Flat Shaded 3D models
Post by: selmiak on Mon 17/03/2014 21:39:47
my head exploded just a bit right now!
AGS can party like its 95 now :D
Khris, this is great! Can you also put a pixel/bitmap texture on these lowpoly models?
Title: Re: Flat Shaded 3D models
Post by: Khris on Mon 17/03/2014 22:07:46
Thanks guys, but it's actually not that complicated, believe it or not :)

Getting this to work in 8bit should be pretty simple; I'll try it later. I think four or five shades should be enough to give decent results.
Shading without a lightsource is possible, sure, but it will look a lot less impressive ;)

As for texturing this, no way. Even texturing a single cube will bring the frame rate down to single digits, unfortunately. At least with pure AGSScript; one could of course use a plugin to do this, but what's the point? It's probably more reasonable to use another engine altogether in that case. Or use blocky raytracing instead.

Here's a four color version:
(http://i.imgur.com/y7esLsi.png)
This does not matter at all for speed though, as you can see ;D
Title: Re: Flat Shaded 3D models
Post by: Scavenger on Tue 18/03/2014 06:37:27
That's looking great, Khris! I can't wait to be making models to put in an AGS game. It'll be the most advanced game of 1992.

Regarding texturing, there's no way you could make perspective correct textures, but flat on textures might be possible, if only technically:

(https://dl.dropboxusercontent.com/u/50882197/crit/3D_plaid_texture.gif)
By drawing the triangle on another surface, using that as a template to cut out a base texture, and blitting that on the model's drawing, you could get the kind of "endless field" effect that was used in Escape from Monkey Island, and a lot of cheaper animations. If you have sprites with the different levels of brightness, you could even retain the 3D effect whilst having the texture.

The problem here would be that you'd require 10-20 extra commands per poly, and the effect wouldn't be that great.
Title: Re: Flat Shaded 3D models
Post by: Khris on Tue 18/03/2014 14:49:37
Flat textures could be shaded in a 16 or 32 bit game by drawing a semi-transparent black rectangle on top.

I did a quick speed test regarding perspective texturing:
(http://i.imgur.com/NbGqXbK.png)

The numbers speak for themselves, I guess :(
When I drew every other pixel, I got up to 26 FPS.
Title: Re: Flat Shaded 3D models
Post by: Scavenger on Sat 29/03/2014 00:24:34
So do you think this solution is workable in AGS? Does it go any faster if you manually set each tri's colour as a static thing instead of calculating it? I know I'd probably be able to create prettier looking models that way - I don't really have much use for lighting, it just gets in the way of faking texture, and though lighting a model is neat, it's practicality is pretty limited for what I'd use it for - the majority of my game has a very basic flat colour/cel shaded style. Even if I could get 256 tris with just flat colours without slowdown, that would be enough for me, I can work around pretty much any limit.

(Also, would it ease up on the processing if it was rendered at half-speed? It could still be pretty smooth, but due to it's simplicity it wouldn't need to be super smooth, and you could split up the processing between two frames instead of doing it all on one)

Thankyou again for your help!
Title: Re: Flat Shaded 3D models
Post by: Monsieur OUXX on Mon 18/01/2016 15:15:56
Sorry for necro-posting, but I would really, really like the source to this (flat-shaded 3D and texturing) to be made available. I genuinely think that it could benefit the AGS community, and it would be the base for some AGS tool that I'd like to develop. Khris, what says you?
Title: Re: Flat Shaded 3D models
Post by: Khris on Thu 31/05/2018 17:24:42
I'll necro-post again because I was asked for the source and saw you asking for it, too.
Here it is: https://drive.google.com/open?id=1CpA2newcPHNFaTtFmOCgXak2hX1b1pcs
Title: Re: Flat Shaded 3D models
Post by: Crimson Wizard on Thu 31/05/2018 20:44:28
Quote from: Khris on Thu 31/05/2018 17:24:42
I'll necro-post again because I was asked for the source and saw you asking for it, too.
Here it is: https://drive.google.com/open?id=1CpA2newcPHNFaTtFmOCgXak2hX1b1pcs

Maybe unrelated to the original question, but I got curious about this yesterday, don't remember why, so decided to finally learn how to work with transformation matrixes, and this was the result:
Spoiler

(https://i.imgur.com/S6VlIsA.gif)
[close]

Had this silly dream of making a game in filled triangles since playing old DOS simulators :).

I don't post any code yet, since its a terrible mix of several C++ snippets found in the web. But I finally know how to compose rotation matrix (better late than never lol).
https://www.dropbox.com/s/xrrejaawe0l3oku/Test3DPolygons.zip?dl=0
Controls: Q/W, A/S, Z/X - move camera in 3 axes, E/R, D/F, C/V - rotate around 3 axes.
It's bugged (no visibility check, perspective is weird, and rotating camera opposite way around makes triangles appear all over the screen).

I was thinking maybe using your code as a reference and mix in lighting too :).
Title: Re: Flat Shaded 3D models
Post by: Khris on Thu 31/05/2018 21:16:15
Quote from: Crimson Wizard on Thu 31/05/2018 20:44:28It's bugged (no visibility check, perspective is weird, and rotating camera opposite way around makes triangles appear all over the screen).
You can solve the 1st and 3rd issue with frustum culling, btw. Welcome to hell ;)
Title: Re: Flat Shaded 3D models
Post by: Snarky on Thu 31/05/2018 21:39:29
I'm pretty sure Frustum Culling is one of the wizards at Unseen University. :P
Title: Re: Flat Shaded 3D models
Post by: Scavenger on Fri 01/06/2018 01:20:57
(https://i.imgur.com/x9R3dTn.png)
Tested out one of my own models, it's exciting to see! Looks like you can safely render around 200 polys without getting much slowdown (this model's about 500). And there are some geometry errors I'm getting which I'll have to iron out myself. But so far: Promising!
Title: Re: Flat Shaded 3D models
Post by: eri0o on Fri 01/06/2018 03:35:26
Oh... 3D characters in 2D background like Alone in the Dark in a module? (nod)
Title: Re: Flat Shaded 3D models
Post by: Crimson Wizard on Fri 01/06/2018 10:14:58
TBH, I think it would be better to move rendering code to plugin, if you find a way to transfer drawing surface or bitmap pointer between script and plugin code.
Title: Re: Flat Shaded 3D models
Post by: Scavenger on Fri 01/06/2018 11:55:06
Quote from: Crimson Wizard on Fri 01/06/2018 10:14:58
TBH, I think it would be better to move rendering code to plugin, if you find a way to transfer drawing surface or bitmap pointer between script and plugin code.

Yeah, it's perfectly possible, you can edit a sprite like it was an array in the plugin code, which is how I do all my graphical effects. I'd do it myself if I could understand the code, which is a long way off yet. My C++ isn't good enough to handle it, unless there is a lot of overlap between the AGSScript and C.

Additionally, is it possible to reverse the projection, so that if I point at certain screen coords, I could find out which polygon is being rendered there? It doesn't have to be particularily fast, but it'd be useful in making a painting tool.
Title: Re: Flat Shaded 3D models
Post by: Crimson Wizard on Fri 01/06/2018 12:46:55
Quote from: Scavenger on Fri 01/06/2018 11:55:06
Additionally, is it possible to reverse the projection, so that if I point at certain screen coords, I could find out which polygon is being rendered there? It doesn't have to be particularily fast, but it'd be useful in making a painting tool.

This is done with raycast, that's all I know.
Title: Re: Flat Shaded 3D models
Post by: Khris on Fri 01/06/2018 12:49:12
Yeah, you need to turn the mouse coordinates into 3D camera screen coordinates, unproject them into the world, then intersect the line camera-mouse with all triangles. Then find the closest one of all that get hit.
Title: Re: Flat Shaded 3D models
Post by: Phemar on Sun 24/06/2018 09:20:14
(https://i.imgur.com/CIFZps7.png)

I'm always late to the party...

I started working on a 3d module a few years ago, but gave up. I came back to it last week and rewrote the thing from scratch. I just managed to implement some clipping against the screen boundaries using a version of the Sutherland-Hodgman algorithm (although mine clips at the raster stage, which is not very efficient, I'll consider moving it to before the perspective divide at some point).

It has a light source (sun), the shade is just calculated by comparing the triangle's normal to a vector from the sun, and the tint is customizable.

I'm using a python script to export vertex and triangle information from Blender to AGS script, and once I figure out how to export RGB values from a triangle's material, every triangle will be able to have its own unique tint.

You can move around the scene just like you would in any fps, camera look and WASD, (strafe and forward/backward)

As you can see I have no Z sorting yet. Well, I had one that used the average of all 3 Z values from a triangle, but the sorting algorithm slowed everything to a halt. (Was a bubble sort function, which used an index array into the original array instead of destroying the original array). Since I can't Z-Sort, and I'm using the DrawTriangle function instead of drawing each individual pixel, I can't use the z-buffer method either.

How have you guys managed to solve the Z-sorting issue?

(also, you can see something's not quite right with my backface culling function! I think it's because the vector from the player to the triangle isn't normalized, but haven't tested that yet).

Doing this thing in AGS script is tough, without any support for vec3/vec4 formats, 2d arrays or structs within structs. Oh well!

Edit: Holy crap, khris, I just looked at your code and I had no idea I could write functions that returned arrays in AGS. That would have made this soooo much easier! Time to do a refactor, I guess... Sometimes I forget how powerful AGS Script can be. I guess it's because I haven't made a game since AGS 2.62 lol.
Title: Re: Flat Shaded 3D models
Post by: Crimson Wizard on Sun 24/06/2018 12:33:34
Quote from: Phemar on Sun 24/06/2018 09:20:14
Doing this thing in AGS script is tough, without any support for vec3/vec4 formats, 2d arrays or structs within structs. Oh well!

You now can declare user managed types like this:
Code (ags) Select

// declaration in script.ash
managed struct Vector4f
{
    float x;
    float y;
    float z;
    float w;

    import static Vector4f *Newf(float x, float y, float z, float w);
    import static Vector4f *NewVec(int x, int y, int z);
    import static Vector4f *NewVecf(float x, float y, float z);
    import static Vector4f *NewPt(int x, int y, int z);
    import static Vector4f *NewPtf(float x, float y, float z);
};

// In script.asc
static Vector4f *Vector4f::Newf(float x, float y, float z, float w)
{
    Vector4f *v = new Vector4f;
    v.x = x;
    v.y = y;
    v.z = z;
    v.w = w;
    return v;
}


They are still limited in some parts, and may work slightly slower than with global variables.
But then you can do something like:

Code (ags) Select

struct Matrix44
{
    float x[16];
    import Vector4f *Transform(Vector4f *v);
}
Title: Re: Flat Shaded 3D models
Post by: Phemar on Sun 24/06/2018 14:04:22
Crimson, that's awesome.

And here I was doing it like this:
enum Coordinates {
  eX = 0,
  eY = 1,
  eZ = 2,
  eW = 3,
};

struct Vertex
{
  float world[3];
  float camera[3];
  float screen[3];
  float normalized[3];
  int raster[2];
};

struct Triangle
{
  int vertex[3];
  float vector1[3], vector2[3];
  float vectorToSource[3];
  float normal[3];
  float center[3];
};


Then declaring an array of Triangles and Vertices and accessing them like this:

Vertex mesh_verts[MAX_VERTICES];
Triangle mesh_tris[MAX_TRIS];

//and then to access:
mesh_verts[mesh_tris[24].vertex[0]].raster[eX] = //whatever


Your way is basically what I wanted to do when I started, but I wasn't sure how to do it in AGS.