AuthorTopic: Pixel Shaders  (Read 20073 times)

Offline PixelPiledriver

  • 0011
  • **
  • Posts: 997
  • Karma: +6/-0
  • Yo!
    • View Profile
    • My Blog

Pixel Shaders

on: May 21, 2012, 10:15:16 pm
The purpose of a Pixel Shader is to control the color of a rendered pixel.
Read this if you are unfamiliar with the topic.

I've taken interest in writing a 2D lighting Shader.

Lighting depends on many variables.
But as a massive simplification it depends on 2.
Surface direction (normal) and light source position:


In 3D art getting a normal is easy.
The data is already there as it is essential to how it is rendered.
But 2D art is different.
Altho we can find the normal of certain pixels, like the outer edges, there is no "physical" axis.
Surface normals are created by the artist and kept consistent only by choice.
It's exactly this sort of constructed fakeness that keeps me interested in art.
My purpose is not to replace per pixel artistic decisions of color.
It is to add another layer of control to a sprite that is interactive in a game engine.

We can represent direction as a color.
This is commonly thought of as Normal Mapping.
We can use an extra map to light a 2D image.

So first I had to figure out what kind of axis to pull data from.
I started with a 2-axis format:

This had some appealing results (which are lost, forgot to take screenshots), but I felt the control was a little off.

Then I tried using a quadrant method using the Blue channel to determine quadrant.

The idea was to make it easier to find direction.
But I found the setup annoying to work with and abandoned it pretty quickly.

Having a third access could remove the need for quadrants.
My first thought was to use this 3-axis setup:

It reminds me of Barycentric Coordinates and therefore has some interesting properties.
It could have worked but I tried to look for other answers.

Then I came to this 3-axis setup:

It has direction and matches how we traditionally think of a 3D axis making it easier to think about and use.
This is what I'm using now, and it works well.

So here's the progression of getting the base code to work.
I'm writing this from scratch and tweaking it to my needs.
The light source was from the mouse position so I could move it around and see changes quickly.
Old stuff and mistakes towards the top, new stuff and properly working towards the bottom.


The idea is to draw a normal map by hand.
Reducing the number of colors makes surface direction more apparent.
It's easier to grab from and stay consistent.


Manually drawing the normal map, such as the "brick" pattern on the sphere, in theory seems crazy.
But it ends up having really interesting and appealing results despite the fact that its a normal map defined with solid color lines.


Here's some more test results using a sprite and 3 different types of normal map:


Using multiple spheres for normals creates a crapload of distortion, but it's quick and easy to setup.
The last row is starting to actually look decent, even though it uses the multi-sphere normal map.
It's a bit too subtle but its also much more noticeable and cool when it happens in realtime and changes based on position.

Manually painting the normals has much more potential (and is my original goal of coding this) but I have not yet taken the time to make a really nice map.
That'll be my next test, probably on something static.
Obviously it's less expensive to use on static assets but is still doable for animations.

There's still a lot of work to do.
Even if you're not a programmer feel free to comment.
It could lead to a much better shader or other features.
And knowing that it is, we seek what it is... ~ Aristotle, Posterior Analytics, Chapter 1

Offline Conzeit

  • 0100
  • ***
  • Posts: 1448
  • Karma: +3/-0
  • Camus
    • conzeit
    • View Profile
    • CONZEIT

Re: Pixel Shaders

Reply #1 on: May 22, 2012, 02:07:21 am
wow, what an interesting idea  ;D

hmmm first thought in my head is you might want to program for the possibility that some people might not be going for a realistic representation of light, even if you're doing celshading you might want to give a sense of backlighting or fill lighting

http://udoncrew.deviantart.com/art/Fighting-Evolution-GUILE-53508437 This example I think shows well some (almost) backlighting with the sunlight, and the fill light towards the botton of the figures. I think most people would want to aproach this as a real-time photoshop filter, so it should be suitable for different aesthetics, or even maybe for making light completely unlike light. I think sometimes one of the coolest thing about 2D art is how meticulously light sometimes defines features when real light would never do such thing.

Now, to comment on the aproach that got the best results, it might be a good idea to be able to feed the program an outline and tell it these are the edges of the figure. For example imagine you feed your Princess'es outlines, from that the program can fill in the rest of the figure trough embossing around those edges, making a product somewhat like your spheres normal map,  then from there you can just adjust which parts are actually in front and which are towards the back by bringing them forward/backwards like you would with any photoshop layer or any layer based program.


I have no idea wether that made any sense to anyone but me but I hope it gives you some kind of inspiration atleast :p

BTW, thinking about making something 2d into 3d reminded me of the way photoshop uses depth maps to produced displaced images, and people use that to make stereoscopic 3d pictures. That spawned two thoughts 1-why arent you using depth maps to produce the normal maps? 2-you might want to look at photoshop tutorials on displacement maps to get some ideas for how artists usually think of 3difying a 2d image.


PS: You've been making some truly incredible crits on animation, way back when I used to be the only one who cared to make animation crits but I never had the experience or generosity to make crits as rich and helpful as those you've made (making screenshots of every little step to get Ggale to your animation bidding is what I call generosity).

I'm glad I get to see you inject so much life into good ol pixelation =)

Offline Tourist

  • 0010
  • *
  • Posts: 376
  • Karma: +1/-0
    • View Profile

Re: Pixel Shaders

Reply #2 on: May 22, 2012, 03:03:21 am
It looks like you're reinventing Zbrush.  Zbrush is mostly 3d and surface modeling these days, but it started with 2d brushes that painted pixels with surface normals.  Or maybe just a z-buffer that was used for real-time lighting, the effect is the same. 

The user could choose from several brushes, some that would paint flat, some that would build up the image, others that would flatten it down.  These could be combined with various colors or textures so that you could paint a color and height at the same time.  Lighting was separate, and a user could alter the lighting direction at any time.

Here is a link that sort of covers this feature: http://www.pixologic.com/zbrush/features/2_5D/


If you're using software for processing the normals, maybe take a look at these articles.  They were written before pixel shaders were around, so the code might not be useful, but the math and logic are still good. 

http://www.gamedev.net/reference/articles/article1191.asp
http://www.gamedev.net/page/resources/_/technical/math-and-physics/higher-accuracy-quantized-normals-r1252

Representing the data as unit normals (where x^2 + y^2 = z^2) might be better than using independent variables.  With independent variables,  x = y = z = 64 has the same normal as x = y = z = 128.  Or just store it as theta and rho (or even cos(theta) and rho), which would front load the calculations but be faster if you were planning to do this real time in a game engine.

Hope this helps,
Tourist

Offline BladeJunker

  • 0001
  • *
  • Posts: 84
  • Karma: +0/-0
  • Know your limits, then break them.
    • View Profile

Re: Pixel Shaders

Reply #3 on: May 22, 2012, 03:06:52 am
Well I like the concept and I consider it the next best step up from earlier more two dimensional lighting systems. I definitely think 2D in general should use everything afforded by modern technology like normal mapping and frame morphing, I certainly like what Vanillaware has done.

Drawing normals by hand doesn't sound that crazy to me since its essentially what CG modelers do in terms of surface normals. I definitely think Zbrush and the like would help with creation of such sprite layers. Its hard to say where you draw the line or not as you could probably get better results through CG model rendering with painterly passes afterwards.
Here's someone using CG as a base for sprite creation that could help maybe, basically you create a basic model to get the rudimentary normal map(Possibly with subdivision.)and paint in the more complex stuff afterwards. :-\ Idk, its hard to stick to pure 2D with these more complex demands.
http://forums.tigsource.com/index.php?topic=167.11274

Oh and I love that Princess Piledriver sprite work, Id love to play that game. ;D

Offline blumunkee

  • 0010
  • *
  • Posts: 325
  • Karma: +1/-0
    • View Profile

Re: Pixel Shaders

Reply #4 on: May 22, 2012, 04:31:52 am
Good stuff here. Seems like you could generate normal maps from the lightness values of the sprites. They'll probably still need some hand tweaking, but it should still speed up the process.

Offline API-Beast

  • 0010
  • *
  • Posts: 292
  • Karma: +0/-0
    • beast_pixels
    • http://pixeljoint.com/p/35725.htm
    • View Profile

Re: Pixel Shaders

Reply #5 on: May 22, 2012, 05:09:31 pm
Ah, thats something I have thought about too.

For creating the normal maps my idea was to paint a bump map and use a program like CrazyBump to generate a normal map out of it. Needs some exercise to get some good normal maps, I think.

Another idea would be drawing a layer on top of your sprite with a light from the top in green and from the right in red. But I need to do some experimenting on that.

My concept was instead of having light sources like you have in 3D that you have a "light pass", e.g. that every light source is a sprite and composed into a single layer (additive or maximal blending).
The normal map is then simply a offset for the texel fetch. Red is the offset in X-Direction, Green the offset in Y-Direction (both of course transformed, the example image is using those values in a linear fashion but in dynamic applications something expontial will probably work better). Blue is Z in 3D, but since you don't have that in 2D you can use it for intensity e.g. how much light this pixel receives.




« Last Edit: May 22, 2012, 05:15:43 pm by Mr. Beast »

Offline Helm

  • Moderator
  • 0110
  • *
  • Posts: 5159
  • Karma: +0/-0
    • View Profile
    • Asides-Bsides

Re: Pixel Shaders

Reply #6 on: May 22, 2012, 05:50:41 pm
It'd be really interesting if the normals for a sharp, pixel-crisp sprite were also sharp-pixel crisp. And if the lighting was forced to be less gradienty as well. Closer to a flatshaded vector coloring, really. It's difficult to explain what I mean.

Offline Conzeit

  • 0100
  • ***
  • Posts: 1448
  • Karma: +3/-0
  • Camus
    • conzeit
    • View Profile
    • CONZEIT

Re: Pixel Shaders

Reply #7 on: May 22, 2012, 08:49:01 pm
I think we instinctively know what you mean Helm, we pixelartists always want everything to be sharp :p I was trying to get to the same point with my example of the Guile ending comic up there, I think the best way to think of it would be thinking of the shader for this as a cel-shader/toon-shader that has the option to be pixel precise.
« Last Edit: May 22, 2012, 08:55:40 pm by Conceit »

Offline Ryumaru

  • Moderator
  • 0100
  • *
  • Posts: 1683
  • Karma: +0/-0
  • to be animated soonly
    • ChrisPariano
    • View Profile

Re: Pixel Shaders

Reply #8 on: May 23, 2012, 05:25:53 am
It'd be really interesting if the normals for a sharp, pixel-crisp sprite were also sharp-pixel crisp. And if the lighting was forced to be less gradienty as well. Closer to a flatshaded vector coloring, really. It's difficult to explain what I mean.

This. I love the idea of dynamic real time lighting that still holds some of the pixel aesthetic to it. This stuff is way above my head but it all looks like nice experimentation! would love to see a princess piledriver game with beautiful animations and sexy lighting!

Offline PypeBros

  • 0100
  • ***
  • Posts: 1220
  • Karma: +2/-0
  • Pixel Padawan
    • PypeBros
    • View Profile
    • Bilou Homebrew's Blog.

Re: Pixel Shaders

Reply #9 on: May 23, 2012, 06:52:22 am
I remember of robotacon trying to do something similar in his arcade academy project. Haven't compared the two approaches yet, though.