OrbitalReign's career change

The Partridge Family were neither partridges nor a family. Discuss.
OrbitalReign
Posts: 19
Joined: July 17th, 2017, 1:24 pm

OrbitalReign's career change

Post by OrbitalReign » August 17th, 2017, 11:06 am

Welcome to my journal.
Well all the cool kids are doing it so i guess i should do a journal thing.

So the short of it, I'm a 30 year old construction worker ( Plasterer to be specific ) that left halfway through the last year of high school to help my dad at work and Iv been stuck ever since.

13 years on or so and my joints are all buggerd to the point i sound like a walking sailing ship and with not much in the way of formal training I'm up a pretty shitty creek. But! there is hope in a odd way, my Fiance is on a Transplant list for new lungs and kidneys and as such i have to take 6 months of work to care for her post-transplant.

The wait list for the transplant is about 6 to 18 months they say and then shit hits the fan and our life gets flipped on its head....

annnd to digress from a probably share to much story, I get 6 months of sitting on my arse to start a new career.

So i chose probably to my detriment a career as a game programmer or more specific an indie developer with this thing as a record of my failings and successes.



This is the little isometric rts/circular tower defence I'm working on. its just an empty world that you can move around and zoom in and out at the moment and a little cube character that you can drive around. wsad moves the cube, arrows move the frame around the world and 'z'x' zoom in and out, and 'h' puts the frame back at "home".
60 Plus hours of hair pulling debugging to get it the where it is; just if you were wondering.

https://github.com/OrbitalReign/DigDefence.git
DigDefence.JPG
(149.14 KiB) Not downloaded yet
DigDefenceTornado.JPG
(249.57 KiB) Not downloaded yet
Last edited by OrbitalReign on August 23rd, 2017, 10:43 am, edited 1 time in total.

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: OrbitalReign's career change

Post by chili » August 22nd, 2017, 1:22 am

Hmmm, this one went under my radar. I'll take a look and add it to the list for the next show-and-tell.

You seem to have rolled a big old snake-eyes; I hope you can turn it around mate. Good luck to you and your fiancee. I'll keep an eye on this thead.
Chili

OrbitalReign
Posts: 19
Joined: July 17th, 2017, 1:24 pm

Re: OrbitalReign's career change

Post by OrbitalReign » August 23rd, 2017, 10:52 am

Cheers mate,

Just added a weird orbital (not a pun) affect to the enemy's in my game while messing around with their AI targeting. maybe someone is interested in making a tornado of poos??

OrbitalReign
Posts: 19
Joined: July 17th, 2017, 1:24 pm

Re: OrbitalReign's career change

Post by OrbitalReign » August 26th, 2017, 8:39 am

so iv been working on some thing called a half space triangle thingy from some guy called nick from devmaster forum http://forum.devmaster.net/t/advanced-r ... ation/6145.
My buildings in my game are all wire frame and basically i wanted to have a black mask behind my buildings so they could be drawn on top without other stuff showing through and wound up learning how polygons are rendered. I'm going to assume there is some easy way or built in to do this with direct x or something but it was handy to know.

Here's what i ended up with if anyone is interested in playing around with it or you can pull it from my repo https://github.com/OrbitalReign/DigDefence.git. I made a custom min max function too because the one i tried only had 2 inputs.
Anywho to get my head around the maths i pretty much had 3 pages of a grid book filled with triangles and equations to figure out what the hell was going on but persistence pays off and it works for what i want.

And yes i could have just drawn them with putpixel calls but i couldn't get the converter to work in the beginning so I'm stuck with wire frame till i get up to the intermediate lessons.

That being said I kinda like the challenge of the wire frame.
Spoiler:

Code: Select all

void Graphics::half_Screen_tri(const Vec v1, const Vec v2, const Vec v3, Color c)
{

	// 28.4 fixed point coords
	const int x1 = (int)round(16.0f * v1.vx);
	const int x2 = (int)round(16.0f * v2.vx);
	const int x3 = (int)round(16.0f * v3.vx);

	const int y1 = (int)round(16.0f * v1.vy);
	const int y2 = (int)round(16.0f * v2.vy);
	const int y3 = (int)round(16.0f * v3.vy);
	// deltas
	const int DX12 = x1 - x2;
	const int DX23 = x2 - x3;
	const int DX31 = x3 - x1;

	const int DY12 = y1 - y2;
	const int DY23 = y2 - y3;
	const int DY31 = y3 - y1;

	// fixed point deltas 
	const int FDX12 = DX12 << 4;
	const int FDX23 = DX23 << 4;
	const int FDX31 = DX31 << 4;

	const int FDY12 = DY12 << 4;
	const int FDY23 = DY23 << 4;
	const int FDY31 = DY31 << 4;

	// bounding rect 
	int minx = (custom_min(x1, x2, x3) + 0xf) >> 4;
	int maxx = (custom_max(x1, x2, x3) + 0xf) >> 4;
	int miny = (custom_min(y1, y2, y3) + 0xf) >> 4;
	int maxy = (custom_max(y1, y2, y3) + 0xf) >> 4;

	// check block size 
	const int quad = 8;

	// start in corner of block
	minx &= ~(quad - 1);
	miny &= ~(quad - 1);

	// half edge constants 
	int C1 = DY12 * x1 - DX12 * y1;
	int C2 = DY23 * x2 - DX23 * y2;
	int C3 = DY31 * x3 - DX31 * y3;

	// correct for fill convention 
	if (DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
	if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
	if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;

	// loop though blocks of quad

	for (int y = miny; y < maxy; y += quad)
	{
		for (int x = minx; x < maxx; x += quad)
		{
			// corners of block check
			int X0 = x << 4;
			int X1 = (x + quad - 1) << 4;
			int Y0 = y << 4;
			int Y1 = (y + quad - 1) << 4;

			// evaluate halfspace functions
			bool a00 = C1 + DX12 * Y0 - DY12 * X0 > 0;
			bool a10 = C1 + DX12 * Y0 - DY12 * X1 > 0;
			bool a01 = C1 + DX12 * Y1 - DY12 * X0 > 0;
			bool a11 = C1 + DX12 * Y1 - DY12 * X1 > 0;
			int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);

			bool b00 = C2 + DX23 * Y0 - DY23 * X0 > 0;
			bool b10 = C2 + DX23 * Y0 - DY23 * X1 > 0;
			bool b01 = C2 + DX23 * Y1 - DY23 * X0 > 0;
			bool b11 = C2 + DX23 * Y1 - DY23 * X1 > 0;
			int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);

			bool c00 = C3 + DX31 * Y0 - DY31 * X0 > 0;
			bool c10 = C3 + DX31 * Y0 - DY31 * X1 > 0;
			bool c01 = C3 + DX31 * Y1 - DY31 * X0 > 0;
			bool c11 = C3 + DX31 * Y1 - DY31 * X1 > 0;
			int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);

			// skip block when outside an edge
			if (a == 0x0 || b == 0x0 || c == 0x0) continue;
			// accept whole block when totally covered
			if (a == 0xf && b == 0xf && c == 0xf)
			{
				for (int iy = 0; iy < quad; iy++)
				{
					for (int ix = x; ix < x + quad; ix++)
					{
						PutPixel(ix, iy + y, Colors::Green); //green for test. adds black mask to building silhouette
					}
				}
			}
			else  // partially coverd block
			{
				int CY1 = C1 + DX12 * Y0 - DY12 * X0;
				int CY2 = C2 + DX23 * Y0 - DY23 * X0;
				int CY3 = C3 + DX31 * Y0 - DY31 * X0;

				for (int iy = y; iy < y + quad; iy++)
				{
					int CX1 = CY1;
					int CX2 = CY2;
					int CX3 = CY3;

					for (int ix = x; ix < x + quad; ix++)
					{
						if (CX1 > 0 && CX2 > 0 && CX3 > 0)
						{
							PutPixel(ix, iy, Colors::Green); //green for test. adds black mask to building silhouette
						}

						CX1 -= FDY12;
						CX2 -= FDY23;
						CX3 -= FDY31;
					}

					CY1 += FDX12;
					CY2 += FDX23;
					CY3 += FDX31;
				}
			}
		}
	}
}

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: OrbitalReign's career change

Post by chili » August 26th, 2017, 10:26 am

Haha, the tornado of boxes looks sweet. What you've got there is basically isometric projection. I do love me some isometric graphics.
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: OrbitalReign's career change

Post by albinopapa » August 26th, 2017, 9:15 pm

Some of the code reminds me of the barycentric rasterization stuff I did a while back. I didn't understand it then, the math portion, and I don't understand it now :). Chili uses a scanline rasterization technique in his 3D Fundamentals and his old Advanced series and I think again in the HUGS series.

Each has it's pros and cons I'd say. The barycentric method does seem to require less calculations and once you find the barycentric coordinates, you can use those to interpolate values for texture coordinates and normals if you want to go that far. Another pro is there is no need to figure which vertex is at the top of the triangle as with the scanline method. The only con I've found is having to scan through a complete rectangle, well, not having to, but I've tried traversing the edges of the triangle (combining the two methods) and there doesn't seem to be much of a performance boost for very large surfaces. Basically, if it covers a large portion of the screen, you're still going to get low performance. On the other hand, looping through a rectangular region using SIMD instructions (handles 4, 8 or 16 pixels at a time) is easier than using the scanline method.

The scanline pro is that the maths are pretty much straight forward. Divide a triangle into two smaller triangles so you end up with one with a flat bottom and one with a flat top. Traverse the left and right edges scanning the line between the two using the slope of each as a starting and ending point. This means you never draw or even check outside of the triangle. The con(s) would be that you must reorder the vertices so that you can start from the top of the triangle and scan down, from left to right. Interpolation for texture coordinates and normals must be calculated at each step using linear interpolation. Since SIMD instructions are in clusters of 4, 8 or 16, you are stuck having two sets of instructions ( for simplicity sake ). One set for lines with a width < 4 and a set for lines with a width >= 4 just for SSE or >= 8 for AVX and >= 16 for AVX/512. Vertex transformations and setting up the triangles for rasterization is negligible compared to the actual rasterization portion of rendering to screen.

Anyway, looks cool thanks for sharing.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

OrbitalReign
Posts: 19
Joined: July 17th, 2017, 1:24 pm

Re: OrbitalReign's career change

Post by OrbitalReign » August 27th, 2017, 4:42 am

Cheers guys,
also you gave me a lot to look into as i had to google half of what you were talking about albino.
I'm still amazed at how much goes into the graphics rendering yet it can keep up with the frame rate.. or not sometimes.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: OrbitalReign's career change

Post by albinopapa » August 27th, 2017, 8:49 am

Yeah, look into C++ Amp if you really want to speed things up. SSE is upto 4x faster, AVX is upto 8 times faster and AVX/512 is upto 16x faster than normal x86/x64 float/int processing, but using your GPU is like 1000x faster. Even if you multithread and get perfect scalability with AVX/512 you still end up with 16 * threads, so 32x for 2 threade, 64x for 4 threads and 128x for 8 threads. So even if you could run on a AMD thread ripper with 16 threads, you'd only get a quarter of the power of the GPU.

Stick to directx for your 3D needs, it pays off. However, if you are looking to improve other aspects like physics, where the D3D pipeline doesn't actually help, then C++ AMP, OpenCL or DirectCompute is where you need to turn. C++ AMP is nice because you only need to know C++. DirectCompute requires knowledge of shaders and DX api and same with OpenCL, you need to learn the API.

C++ AMP, for VS uses DX11 DirectCompute under the hood, but you only need to know C++ to get it running. To make it run efficiently, I'm sure you need to understand multithreading, but you can start with the single threaded basics.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: OrbitalReign's career change

Post by chili » August 27th, 2017, 2:38 pm

Yeah this is correct. I've got a kid on the Discord right now making a 3D graphics engine using C++ AMP :D It's not a practical pursuit, but he is aware of it and is doing it shits and giggles I guess.

Direct3D will be able to make use of a bunch of specialized hardware units that you don't have access to in GPGPU, so no question using D3D/OGL/Vulkan is the way to go
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: OrbitalReign's career change

Post by albinopapa » August 28th, 2017, 5:54 am

I've been wanting to do the same for shits and giggles, just haven't gotten around to it. As far as I can tell, the only specialized portion you have access to in C++ AMP is the texture units. You can also access local member ( local in this case means to GPU ) by using tiles. This allows for faster access to data for a group of GPU threads thus improving performance. If you have seen any D3D shaders, the vertex shader for instance, you might have seen a constant buffer usually near the top of the shader file. This data is the same for all threads processing the vertices, tiles would be a good fit here.

In a game where so much is math based and there are usually so many entities to update, C++ AMP would be a great fit. It would take some planning though because there are restrictions. For the most part, you cannot use pointers or references ( there are exceptions ). You'd need to understand multithreading patterns and how to avoid data races. Still, C++ AMP is fun to mess around with and would be beneficial to someone who uses it correctly.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply