So naturally, I bought a HDTV.
But this is no ordinary "High Definition Television". This is a 'F'ing HDTV. It says so, right on the box!
Not only that, but this TV is WAY more realistic that True Life! I didn't even know I could ascend to a higher state of being simply by purchasing a material good! This changes my entire perspective on reality being merely perception!
And, of course, what better way to test a new TV than to use the greatest, most awesome of all videogames to test it's stunning reproduction of color and fast-action packed motion than:
If you cannot recognize this game, I hate you, and you should play it so I do not hate you.
-Z
(P.S. It's called "Tyrian")
Miscellaneous banter, Useful mathematics, game programming tools and the occasional kink or two.
2009-01-25
Odd dream; A New Character Approaches!
Okay, so get this.
Me, mike, vanessa (sorry for sp!) and maria (again! sp!) went to a mall, it was sometime in august apparently, and we were at the beach or something. It seemed like the east coast, slightly foggy, the air was humid, enough to make you have trouble breathing. It was warm though, upper seventies.
This being another odd dream of mine, zombies happen. Not normal zombies, just mutated dead people that seemed to be afraid of light. So, we all stick together, watch some people get mauled/eaten, and find that if we stay in the light, they don't attack us. After moving slowly down into the depths of the mall, we find a Foley's or some department store, which is WELL lit, and get everyone in there and barricade the hell out of it (notice those places are well defended? neat.). There were lots of other people with us, but I for some reason had a sawed off double barreled shotgun that I pulled out of nowhere, and went to go see these zombies. Of course, this is a day or two later, and the zombies had upgraded to RE-type monsters, like those damned hunters or whatever. Oddly though, as soon as I left the store, they didn't even get close to me, they were afraid of my presence, as if I was one of their leaders. They would approach, snarling, dripping blood and fleshy bits from gnarled stained teeth, glistened over with some sort of slime like a fish, making low gurgling, growling noises, yet only strafing in a circle around me, keeping at least 20 feet from my center. I could move at them. and they would jump back in fright. It was a rather empowering feeling, but right then things began to change.
I was more myself (as in, me the fantasy character, Z) and I could sense it, as if my arch nemesis was going to appear and we would fight to the death.
But this was new. some lacky, who looked like the bond from that new blonde movie (screw that) came at me and talked some shit like "master is going to kill you!", walking around like a zombie igor, but not showing any signs of zombification. Of course, as I walked out to this shipyard/gantry, I saw my foe at the end of the tunnel, the lackey running back to report.
Time froze as we both gave eachother that anime eye-stare, piercing and gauging who would die first. Of course, like any popular anime, the outcome is even, in order to create suspense.
It said only one sentence as I approached.
"I am here to avenge your Brother. *evil laugh*"
Now, if you know any of my villians, like Mr "S" and ect... then you know that this all-black satin mime-style creep is kinda odd. He looked feminine, but had a male voice, somewhat androgynous, but wore a black trenchcoat that seemed like leather, but it was fuzzy so it had a matte finish. It was loose, but belted around the odd garb of that solid black one-piece suit, like an acrobat from Cirque de Solie (sp?), and had a scepter that was tiny in the right hand, a floaty demeanor, and his face, was generic. But, it had white diamonds on the eyes like a mime, but no face paint so you could see flesh color. It also wore a hat over black hair that was like a jesters cap. The trenchcoat had a larger than normal collar, and this thing looked ridiculous. My brother would kill fools like this, not hire them to avenge.
Either way, since now it was determined this was to be a Viewtiful Joe style endurance fight with DBZ elements, the camera switches to game mode, and I get a third person view and begin to play the game.
We both had the same amount of health, and were both insanely tough, so, it was kinda crazy. We both had the same abilities, like shoryuken (fire-dragon punch), this wind-dragon-tornado-hadoken style move, lightning blasts, ice missiles, and I had my wristbands as a physical weapon, this joker had that scepter, and there were plenty of generic kung fu moves. We were both ultra strong, so we could lift tons of mass and chunk em at eachother.
So, I dashed forward, and attacked, it laughed and began toying with me, copying my moves like shadow link, intermittently using a weird crystal move that made these hollow diamonds appear in random places, which then fired quickly at where you were going, forcing you to dance and dodge, but you always took a lot of hits.
So, I learned it' patterns, and got my first hit in after it uses dragon-fire-wave-bullshit, slide kicking through it with an ice attack then using my wristband powered selfe (slow zoom punches + spin kick + uppercut) to inflict almost a 1/2 healthbar (but we each had 12 full healthbars) . then it jumped back, threw shit at me like giant metal cylinders, I used wind attack to move them slightly ot the side, and then we started hadoken-ing our way to victory, blast after blast, but it used the crystal move and I rolled under that fucker and made him get hit with his own attack, then he whipped around trying to backblow me but I shoved a steel pipe through his chest, which barely did any damage so he yanked it out and threw it away.
The beatings continued, some dark matter gravity-beetle style attacks, and some environmental hazards (that idiot got close to the floor where a giant worm was (wtf?) so I knew it by name and called it, it ate the fucker, but well, that did MAYBE 1/10th a bar of damage, before it killed the worm and tried more crystal bullshit. the entire gantry was sinking apparently, so water was slowly filling our arena.
However, during the fight, this was probably the 10th time I got in close and just kicked the shit out of him with 10+ hit combos via wristband, I just woke up cause I had my 8 hours of sleep.
which sucked, because this was a worthy opponent, and although I was toying with him, it was a good fight, and for being a goofy looking mofo, it was surprisingly fair. No cheap insta-death moves (and yes, if you get eaten in any of my games, it's usually not instantly fatal. Just dodge teeth!) or annoying finishers like "skull pop" or my favorite "hand-through-sternum".
Actually, there were lots of normally fatal to humans moves delivered, like axes kicks, nose-into-brain punches, hands and fists breaking ribcages. But we weren't human, we were videogame characters in a false representation of the real fight. So anything was possible.
All I wanted to do was use my summon and end the fight, but mimeclown was too quick for me to pull it off. Oh well.
Someday, I need to get screencap for my brain.
-Z
Me, mike, vanessa (sorry for sp!) and maria (again! sp!) went to a mall, it was sometime in august apparently, and we were at the beach or something. It seemed like the east coast, slightly foggy, the air was humid, enough to make you have trouble breathing. It was warm though, upper seventies.
This being another odd dream of mine, zombies happen. Not normal zombies, just mutated dead people that seemed to be afraid of light. So, we all stick together, watch some people get mauled/eaten, and find that if we stay in the light, they don't attack us. After moving slowly down into the depths of the mall, we find a Foley's or some department store, which is WELL lit, and get everyone in there and barricade the hell out of it (notice those places are well defended? neat.). There were lots of other people with us, but I for some reason had a sawed off double barreled shotgun that I pulled out of nowhere, and went to go see these zombies. Of course, this is a day or two later, and the zombies had upgraded to RE-type monsters, like those damned hunters or whatever. Oddly though, as soon as I left the store, they didn't even get close to me, they were afraid of my presence, as if I was one of their leaders. They would approach, snarling, dripping blood and fleshy bits from gnarled stained teeth, glistened over with some sort of slime like a fish, making low gurgling, growling noises, yet only strafing in a circle around me, keeping at least 20 feet from my center. I could move at them. and they would jump back in fright. It was a rather empowering feeling, but right then things began to change.
I was more myself (as in, me the fantasy character, Z) and I could sense it, as if my arch nemesis was going to appear and we would fight to the death.
But this was new. some lacky, who looked like the bond from that new blonde movie (screw that) came at me and talked some shit like "master is going to kill you!", walking around like a zombie igor, but not showing any signs of zombification. Of course, as I walked out to this shipyard/gantry, I saw my foe at the end of the tunnel, the lackey running back to report.
Time froze as we both gave eachother that anime eye-stare, piercing and gauging who would die first. Of course, like any popular anime, the outcome is even, in order to create suspense.
It said only one sentence as I approached.
"I am here to avenge your Brother. *evil laugh*"
Now, if you know any of my villians, like Mr "S" and ect... then you know that this all-black satin mime-style creep is kinda odd. He looked feminine, but had a male voice, somewhat androgynous, but wore a black trenchcoat that seemed like leather, but it was fuzzy so it had a matte finish. It was loose, but belted around the odd garb of that solid black one-piece suit, like an acrobat from Cirque de Solie (sp?), and had a scepter that was tiny in the right hand, a floaty demeanor, and his face, was generic. But, it had white diamonds on the eyes like a mime, but no face paint so you could see flesh color. It also wore a hat over black hair that was like a jesters cap. The trenchcoat had a larger than normal collar, and this thing looked ridiculous. My brother would kill fools like this, not hire them to avenge.
Either way, since now it was determined this was to be a Viewtiful Joe style endurance fight with DBZ elements, the camera switches to game mode, and I get a third person view and begin to play the game.
We both had the same amount of health, and were both insanely tough, so, it was kinda crazy. We both had the same abilities, like shoryuken (fire-dragon punch), this wind-dragon-tornado-hadoken style move, lightning blasts, ice missiles, and I had my wristbands as a physical weapon, this joker had that scepter, and there were plenty of generic kung fu moves. We were both ultra strong, so we could lift tons of mass and chunk em at eachother.
So, I dashed forward, and attacked, it laughed and began toying with me, copying my moves like shadow link, intermittently using a weird crystal move that made these hollow diamonds appear in random places, which then fired quickly at where you were going, forcing you to dance and dodge, but you always took a lot of hits.
So, I learned it' patterns, and got my first hit in after it uses dragon-fire-wave-bullshit, slide kicking through it with an ice attack then using my wristband powered selfe (slow zoom punches + spin kick + uppercut) to inflict almost a 1/2 healthbar (but we each had 12 full healthbars) . then it jumped back, threw shit at me like giant metal cylinders, I used wind attack to move them slightly ot the side, and then we started hadoken-ing our way to victory, blast after blast, but it used the crystal move and I rolled under that fucker and made him get hit with his own attack, then he whipped around trying to backblow me but I shoved a steel pipe through his chest, which barely did any damage so he yanked it out and threw it away.
The beatings continued, some dark matter gravity-beetle style attacks, and some environmental hazards (that idiot got close to the floor where a giant worm was (wtf?) so I knew it by name and called it, it ate the fucker, but well, that did MAYBE 1/10th a bar of damage, before it killed the worm and tried more crystal bullshit. the entire gantry was sinking apparently, so water was slowly filling our arena.
However, during the fight, this was probably the 10th time I got in close and just kicked the shit out of him with 10+ hit combos via wristband, I just woke up cause I had my 8 hours of sleep.
which sucked, because this was a worthy opponent, and although I was toying with him, it was a good fight, and for being a goofy looking mofo, it was surprisingly fair. No cheap insta-death moves (and yes, if you get eaten in any of my games, it's usually not instantly fatal. Just dodge teeth!) or annoying finishers like "skull pop" or my favorite "hand-through-sternum".
Actually, there were lots of normally fatal to humans moves delivered, like axes kicks, nose-into-brain punches, hands and fists breaking ribcages. But we weren't human, we were videogame characters in a false representation of the real fight. So anything was possible.
All I wanted to do was use my summon and end the fight, but mimeclown was too quick for me to pull it off. Oh well.
Someday, I need to get screencap for my brain.
-Z
Labels:
dream
2009-01-24
Power is Agony
In summary,
I'm sorry,
In detail,
I got to see parts of the beginning of 'Spirited Away'. Looks like a great movie, buuuut...
When I see things that remind me of how I treated someone, and how I treated them badly, it makes me really sad. My only existing defense to avoid crying like a damned babyis to distract myself with work. If I can be tasked, I can usually forget and ignore those kinds of severe pains.
However, this one seems different, it is hard to explain. It's as if I, in a past life or even an alternate universe really hurt someone I cared about; it would be something similar to killing your mother in front of your little sister whom you made watch, and telling her it was okay, and everything was going to be fine as you burned the corpses. You knew what you did was right, at least at the moment, but as time passed, it became obvious how horrible and sadistic of a person you were, not only to things that deserved it, but directly translated to all things. Lost in a world where no one can either stop or control you, with no guidance or correct answers, there is nothing left you can do, nowhere to escape your apparently assigned fate.
Let me put this another way, if you have a gray area, like so many of life's decisions are, how do you rationalize your choice? The correct answer, is you can't. There ARE right answers, but you can't always see or even choose them. In the mind of a killer, like me, taking someone else's life is not wrong, because nothing IS wrong unless you define it as such. Other people trying to tell me that murder is wrong are not thinking about it correctly; There is no ambiguous, universal good or bad, those are merely ideological representations of what we have decided as a sentient society to obey in order to preserve order, and ourselves. Knowing this is critical, so I restate it simpler:
"There is no right or wrong. There is only do."
So back to what bothers me, apparently, my alternate self hurt a friend that I care abou t today, but, well, circuimstances have changed, and due to things beyond my control I can never talk to that friend again, and as a result I can never apologize or atone for my sins. Now I have the rest of my entire life to live and bleed this curse, professing it to any who will listen.
It's even more confusing to me, as I investigate the lifecycle of one of my own characters; A powerful being allowed to do nearly anything, chained to a simple job, and eventually, thanks to external forces, caused him to fail, and he, single handedly, was responsible for the murder of all the people on his homeworld, his entire family, and himself. I, however, WAS that external force. It was decided, outside of this small bump in the road, that it was to be this way, and nothing could ever stop it. I tried to stop it, since it was a friend of mine, but, ultimately, what I did was load the gun and point it, and made my friend pull the trigger.
This kind of manipulation is downright evil; But what are you to do about it? If you have the power to change the fate of an entire univese, do you do it at the cost of all the others? Does billions of people suffering and dying in a flaming hell bother you? Does it even matter, since that would happen ultimately anyways? Where is this fence? Where are the bounds to this situation we are in? What is keeping these powers from exploding outward, and collapsing in on themselves? Who is in control?
The answer is simple. No one. Everything is only physical. All existence and perception is merely emergent behavior from a simple and well defined system. This is the way it began, and this is the way it will end. No matter how many people, creatures, machines, or even galaxies there are, everything is made of the exact same rules. The rules allow lots and lots of interesting variations, and all things can be explained by them. If you want the quick explaination, Chaos does not exist, it is a modeling tool only.
But, as you may know by now, when you are really powerful, like me, you can lie to yourself.
There's no extra charge to be happy!
Cheers to you, buddy.
I'm sorry.
-Z
I'm sorry,
In detail,
I got to see parts of the beginning of 'Spirited Away'. Looks like a great movie, buuuut...
When I see things that remind me of how I treated someone, and how I treated them badly, it makes me really sad. My only existing defense to avoid crying like a damned baby
However, this one seems different, it is hard to explain. It's as if I, in a past life or even an alternate universe really hurt someone I cared about; it would be something similar to killing your mother in front of your little sister whom you made watch, and telling her it was okay, and everything was going to be fine as you burned the corpses. You knew what you did was right, at least at the moment, but as time passed, it became obvious how horrible and sadistic of a person you were, not only to things that deserved it, but directly translated to all things. Lost in a world where no one can either stop or control you, with no guidance or correct answers, there is nothing left you can do, nowhere to escape your apparently assigned fate.
"There is no right or wrong. There is only do."
So back to what bothers me, apparently, my alternate self hurt a friend that I care abou
It's even more confusing to me, as I investigate the lifecycle of one of my own characters; A powerful being allowed to do nearly anything, chained to a simple job, and eventually, thanks to external forces, caused him to fail, and he, single handedly, was responsible for the murder of all the people on his homeworld, his entire family, and himself. I, however, WAS that external force. It was decided, outside of this small bump in the road, that it was to be this way, and nothing could ever stop it. I tried to stop it, since it was a friend of mine, but, ultimately, what I did was load the gun and point it, and made my friend pull the trigger.
This kind of manipulation is downright evil; But what are you to do about it? If you have the power to change the fate of an entire univese, do you do it at the cost of all the others? Does billions of people suffering and dying in a flaming hell bother you? Does it even matter, since that would happen ultimately anyways? Where is this fence? Where are the bounds to this situation we are in? What is keeping these powers from exploding outward, and collapsing in on themselves? Who is in control?
The answer is simple. No one. Everything is only physical. All existence and perception is merely emergent behavior from a simple and well defined system. This is the way it began, and this is the way it will end. No matter how many people, creatures, machines, or even galaxies there are, everything is made of the exact same rules. The rules allow lots and lots of interesting variations, and all things can be explained by them. If you want the quick explaination, Chaos does not exist, it is a modeling tool only.
But, as you may know by now, when you are really powerful, like me, you can lie to yourself.
There's no extra charge to be happy!
Cheers to you, buddy.
-Z
Labels:
emo
2009-01-18
GL_ARB_vertex_program II
I toyed with it a bit after rock banding it out with "Curetis Siva", the hottest new group to hit the pretend rock band scene.
More results:
This is 35 x Delgadosaurus's, which, he consists of 3700 verticies and 3800 polygons apiece.
Now, like the Asty demo, here's some frightening numbers:
129,500 fully deformed verticies ( 4 x weighted matrix deform + texture + lighting + cell shading) runs at 50 FPS, but only 13 IFPS. Note that the asty demo only had ~30000 verticies, so comparing the 17 / 13 ratio, you can see how linear the addition of verticies is to the GPU load.
Also, the collision in this one is taken out (VA/VBO's only) from this screenshot, yet the CPU load remained high, which is something to investigate. It must have to do with the bus transfer rates from system ram to GPU.
Point is, this kinda opens up the floor for high-poly models, which are nessecary for decent looking games (take a screenshot of Oblivion, it pushes at least 80,000 polygons per frame, all with multiple textures AND a fragment program)
But I care about animations more than textures, at least till I get my artists trained.
More technical notes:
since you have to break up verticies into groups for deformations, each vertex can only be deformed by a set maximum number of bones (4, in this case). You only have 28 bones to play with in the shader, however, if you want anything cool in your shader as well, you are knocked down to about 24 bones maximum. This might be a more useful practical limit anyhow. Storage cost is linear with each matrix used to deform, technically, there is no bone maximum limit, however, imposing one helps alignment constraints. In the ARB shaders, you can have a maximum of 128 instructions (excluding empty lines and comments), so your shaders have to be designed carefully. Only 96 local and 96 environment parameters are allowed in the shaders. Only 12 temporary values are allowed. A infinite number of ALIAS commands are allowed and they do not count against the instruction count (pretend they are #define statements). Loading shaders should be minimized. Switiching shaders should be minimized.
Things to determine:
Does using 4x matrix deform cost less than switching shaders?
Does updating params cost anything signifigant? (think per armature)
How viable is vertex keyframing? (per vertex, you have to load per keyframe switch per model)
How viable is Armature Relative Vertex Keyframes? (weight/offset positions)
Does the iPhone let me use n matricies? How slow is it's matrix palette?
Peace out till next time.
-Z
More results:
This is 35 x Delgadosaurus's, which, he consists of 3700 verticies and 3800 polygons apiece.
Now, like the Asty demo, here's some frightening numbers:
129,500 fully deformed verticies ( 4 x weighted matrix deform + texture + lighting + cell shading) runs at 50 FPS, but only 13 IFPS. Note that the asty demo only had ~30000 verticies, so comparing the 17 / 13 ratio, you can see how linear the addition of verticies is to the GPU load.
Also, the collision in this one is taken out (VA/VBO's only) from this screenshot, yet the CPU load remained high, which is something to investigate. It must have to do with the bus transfer rates from system ram to GPU.
Point is, this kinda opens up the floor for high-poly models, which are nessecary for decent looking games (take a screenshot of Oblivion, it pushes at least 80,000 polygons per frame, all with multiple textures AND a fragment program)
But I care about animations more than textures, at least till I get my artists trained.
More technical notes:
since you have to break up verticies into groups for deformations, each vertex can only be deformed by a set maximum number of bones (4, in this case). You only have 28 bones to play with in the shader, however, if you want anything cool in your shader as well, you are knocked down to about 24 bones maximum. This might be a more useful practical limit anyhow. Storage cost is linear with each matrix used to deform, technically, there is no bone maximum limit, however, imposing one helps alignment constraints. In the ARB shaders, you can have a maximum of 128 instructions (excluding empty lines and comments), so your shaders have to be designed carefully. Only 96 local and 96 environment parameters are allowed in the shaders. Only 12 temporary values are allowed. A infinite number of ALIAS commands are allowed and they do not count against the instruction count (pretend they are #define statements). Loading shaders should be minimized. Switiching shaders should be minimized.
Things to determine:
Does using 4x matrix deform cost less than switching shaders?
Does updating params cost anything signifigant? (think per armature)
How viable is vertex keyframing? (per vertex, you have to load per keyframe switch per model)
How viable is Armature Relative Vertex Keyframes? (weight/offset positions)
Does the iPhone let me use n matricies? How slow is it's matrix palette?
Peace out till next time.
-Z
Labels:
Curetis Siva,
lizard,
opengl,
SDL,
vertex program
2009-01-17
GL_ARB_vertex_program
As the title states, I've been hardcoring this useful tool in order to combat the 'Dancing Lizards' demo performance ratio of 98% CPU / 16 lizards. Now,
We have 35 x Asty's (Asty is just another fat lizard monster, with 800 verts and 1200 poly count. The original dancing lizard was 300 verts with 400 polys.).
The crazy note is, this is a 10% CPU / 35 fully animated characters, including cell shading, deformers, AND whatever else the hell I want to do. This is plenty of performance.
However, if you actually look at this ugly screenshot, you'll notice the statistics in the upper left seem to contradict me; be patient, the IFPS is what is important (~16) which are how many inter-frames there are (1 ms) between render frames. Since all my apps are capped to exactly 50 FPS internal, this means there are 16 ms in there that the game can run and poll for whatever, which is what it does.
Now for some nitty gritty. Let's say you have Asty as a creature in your game (he's quite a friendly fellow!) and you want to make him all sorts of animated, and you overkill the bone count (most of my models have ~120 or so bones, including fingers and IK stuff). Sadly, in the shader model, you cannot feasibly have more than ~28 bones in your shader program at once. (96 parameters available max) This means you have to preprocess groups of verticies that share bones (4 x shader counts, 1 for 1 matrix, 1 for 2 matrix, ect...) so you can actually do all the deformations. This means switching shader programs, which is costly. So, if you want a bunch of fodder enemies, you'll be needing to create some interesting optimization schemes to lower the bone count so you can avoid switching.
In this screenshot, each monster has every vertex with a GLubyte[4] for matrix local palette index (0 to 96, divide by 3) and GLfloat[4] for the weight. I intend to normalize this weight value so I can use bytes, as you generally don't need that accurate of a weigth float. Also, each vertex is renormalized so I can calculate the nifty cell shading value (sum normal dot eye normal = tex coord 0).
Let's look at some assembly:
PARAM K = {1, 0.5, 0, 3.141525968 };
#Skin with any affine matrix:
#PARAM Matrices[] = { program.local[12..84] } <= 28 matricies # [ Xx, Yx, Zx, x pos(1) ] # [ Xy, Yy, Zy, y pos(1) ] #Multiply each axis by it's scale to use scaling, but this will require renormalization for normals. # [ Xz, Yz, Zz, z pos(1) ] #This matrix is CPU computed from: # Let B be the current bone matrix (local to mesh, current pose) # Let M be the original bone matrix (local to mesh, default pose) # Then, W = (B * M^-1) # Send W to shader as matrix in correct form as above #Per vertex in a matrix deformed mesh, # vertex.attrib[6] store n indicies as unsigned bytes (n*1 bytes) # vertex.attrib[7] store n weights as floats (n*4 bytes) #? can we use byte weights? #Requires: RF, R, aMN; ( RF = sum, R = temp, addr = address ) ALIAS R = temp1; #Temp vector ALIAS RF = temp2; #Vector sum (always set to first matrix deform) ALIAS RFN = temp3; #Normal sum (always set to first matrix deform) #For matrix 1 (x)## ARL addr.x, vertex.attrib[6].x; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MUL RF, R, vertex.attrib[7].x; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed (don't forget about scale...) DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MUL RFN, R, vertex.attrib[7].x; #Sum normal with weight as well ################## #For matrix 2 (y)## ARL addr.x, vertex.attrib[6].y; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MAD RF, R, vertex.attrib[7].y, RF; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MAD RFN, R, vertex.attrib[7].y, RFN; #Sum normal with weight as well ################## #For matrix 3 (z)## ARL addr.x, vertex.attrib[6].z; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MAD RF, R, vertex.attrib[7].z, RF; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MAD RFN, R, vertex.attrib[7].z, RFN; #Sum normal with weight as well ################## #For matrix 4 (w)## ARL addr.x, vertex.attrib[6].w; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MAD RF, R, vertex.attrib[7].w, RF; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MAD RFN, R, vertex.attrib[7].w, RFN; #Sum normal with weight as well ################### MOV wNorm, RFN; #Set final normal DP3 R, wNorm, wNorm; #Renormalize normal after deformations (extremely iffy) RSQ R, R.x; MUL wNorm, wNorm, R; MOV wPos.xyz, RF; #Set final position of deformation (could use non-normal weights too...) And that's all you need to make a skinned model in OpenGL using the common ARG vertex program extension. Naturally, people are idiots, and will ask 'why do this instead of GLSL?' and 'This is too old to be useful'. Obviously, if you can do it using the card's assembly language, it's a cinch to move to higher level languages. In fact, it's a incredibly good excercise in understanding not only SIMD instruction stuff, but also general matrix/vector processing units. Plus, this is damned fast and way more portable than GLSL. As some side notes, I have a lot of other nifty shader code, specifically for this things I find important, like: Normal Map colors Cast deformations (spherical) Push-Cast deformations (point -> sphere outward from point)
Water/Perlin noise wobbling
Texture-coordinate lighting
Multiple light cheats
More shading and lighting models
More to come once I give Asty a soul using my IK algorithms and rig him up proper with lotsa delicious bones. THEN we'll see how much CPU we get, and who knows, maybe we'll even get a game demo where you can SSBM other Asty's.
*Note, I also forgot this demo tests a sphere-triangle collision with EVERY loaded triangle. Thus, fixing that, the CPU usage was at MOST 1% for 25 Asty's. So hah. I can't wait to have 1000 lizards dancing. Eat it, GEICO!
-Z
We have 35 x Asty's (Asty is just another fat lizard monster, with 800 verts and 1200 poly count. The original dancing lizard was 300 verts with 400 polys.).
The crazy note is, this is a 10% CPU / 35 fully animated characters, including cell shading, deformers, AND whatever else the hell I want to do. This is plenty of performance.
However, if you actually look at this ugly screenshot, you'll notice the statistics in the upper left seem to contradict me; be patient, the IFPS is what is important (~16) which are how many inter-frames there are (1 ms) between render frames. Since all my apps are capped to exactly 50 FPS internal, this means there are 16 ms in there that the game can run and poll for whatever, which is what it does.
Now for some nitty gritty. Let's say you have Asty as a creature in your game (he's quite a friendly fellow!) and you want to make him all sorts of animated, and you overkill the bone count (most of my models have ~120 or so bones, including fingers and IK stuff). Sadly, in the shader model, you cannot feasibly have more than ~28 bones in your shader program at once. (96 parameters available max) This means you have to preprocess groups of verticies that share bones (4 x shader counts, 1 for 1 matrix, 1 for 2 matrix, ect...) so you can actually do all the deformations. This means switching shader programs, which is costly. So, if you want a bunch of fodder enemies, you'll be needing to create some interesting optimization schemes to lower the bone count so you can avoid switching.
In this screenshot, each monster has every vertex with a GLubyte[4] for matrix local palette index (0 to 96, divide by 3) and GLfloat[4] for the weight. I intend to normalize this weight value so I can use bytes, as you generally don't need that accurate of a weigth float. Also, each vertex is renormalized so I can calculate the nifty cell shading value (sum normal dot eye normal = tex coord 0).
Let's look at some assembly:
PARAM K = {1, 0.5, 0, 3.141525968 };
#Skin with any affine matrix:
#PARAM Matrices[] = { program.local[12..84] } <= 28 matricies # [ Xx, Yx, Zx, x pos(1) ] # [ Xy, Yy, Zy, y pos(1) ] #Multiply each axis by it's scale to use scaling, but this will require renormalization for normals. # [ Xz, Yz, Zz, z pos(1) ] #This matrix is CPU computed from: # Let B be the current bone matrix (local to mesh, current pose) # Let M be the original bone matrix (local to mesh, default pose) # Then, W = (B * M^-1) # Send W to shader as matrix in correct form as above #Per vertex in a matrix deformed mesh, # vertex.attrib[6] store n indicies as unsigned bytes (n*1 bytes) # vertex.attrib[7] store n weights as floats (n*4 bytes) #? can we use byte weights? #Requires: RF, R, aMN; ( RF = sum, R = temp, addr = address ) ALIAS R = temp1; #Temp vector ALIAS RF = temp2; #Vector sum (always set to first matrix deform) ALIAS RFN = temp3; #Normal sum (always set to first matrix deform) #For matrix 1 (x)## ARL addr.x, vertex.attrib[6].x; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MUL RF, R, vertex.attrib[7].x; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed (don't forget about scale...) DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MUL RFN, R, vertex.attrib[7].x; #Sum normal with weight as well ################## #For matrix 2 (y)## ARL addr.x, vertex.attrib[6].y; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MAD RF, R, vertex.attrib[7].y, RF; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MAD RFN, R, vertex.attrib[7].y, RFN; #Sum normal with weight as well ################## #For matrix 3 (z)## ARL addr.x, vertex.attrib[6].z; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MAD RF, R, vertex.attrib[7].z, RF; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MAD RFN, R, vertex.attrib[7].z, RFN; #Sum normal with weight as well ################## #For matrix 4 (w)## ARL addr.x, vertex.attrib[6].w; #Get matrix array index DP4 R.x, Matrices[addr.x + 0], wPos; #Rotate & scale local vector (model position) DP4 R.y, Matrices[addr.x + 1], wPos; DP4 R.z, Matrices[addr.x + 2], wPos; MAD RF, R, vertex.attrib[7].w, RF; #Multiply vector by weight, add to summated deformation vector DP3 R.x, Matrices[addr.x + 0], wNorm; #Rotate normal as needed DP3 R.y, Matrices[addr.x + 1], wNorm; DP3 R.z, Matrices[addr.x + 2], wNorm; MAD RFN, R, vertex.attrib[7].w, RFN; #Sum normal with weight as well ################### MOV wNorm, RFN; #Set final normal DP3 R, wNorm, wNorm; #Renormalize normal after deformations (extremely iffy) RSQ R, R.x; MUL wNorm, wNorm, R; MOV wPos.xyz, RF; #Set final position of deformation (could use non-normal weights too...) And that's all you need to make a skinned model in OpenGL using the common ARG vertex program extension. Naturally, people are idiots, and will ask 'why do this instead of GLSL?' and 'This is too old to be useful'. Obviously, if you can do it using the card's assembly language, it's a cinch to move to higher level languages. In fact, it's a incredibly good excercise in understanding not only SIMD instruction stuff, but also general matrix/vector processing units. Plus, this is damned fast and way more portable than GLSL. As some side notes, I have a lot of other nifty shader code, specifically for this things I find important, like: Normal Map colors Cast deformations (spherical) Push-Cast deformations (point -> sphere outward from point)
Water/Perlin noise wobbling
Texture-coordinate lighting
Multiple light cheats
More shading and lighting models
More to come once I give Asty a soul using my IK algorithms and rig him up proper with lotsa delicious bones. THEN we'll see how much CPU we get, and who knows, maybe we'll even get a game demo where you can SSBM other Asty's.
*Note, I also forgot this demo tests a sphere-triangle collision with EVERY loaded triangle. Thus, fixing that, the CPU usage was at MOST 1% for 25 Asty's. So hah. I can't wait to have 1000 lizards dancing. Eat it, GEICO!
-Z
Subscribe to:
Posts (Atom)