After starting to learn
AGAL 24 hours ago, I've amassed enough "gotchas" that I believe it is time for another edition of The Devil's Details. This time it will focus on Adobe's shader language for
Stage3D, AGAL.
The Devil's Details1.
No Immediate ValuesThis is a bit of a pain. You can't say simply "add ft0, 5, 10" in order to add 5 + 10 and put the result in ft0; instead, you have to place 5 and 10 into constant registers from your program before you render! This applies to any immediate value, so you also can't do something like "mov oc, [1, 0, 0, 1]" to output a red color, or "mul ft0, v0, 2" to double the value of a varying register. You would have to do something like "add ft0.x, fc0.x, fc0.y" or "mov oc, fc0" or "mul ft0, v0, fc0.x".
2.
Lines Must End in a Line Feed!If you are constructing the shader's source code within an ActionScript file by building a string
please do not forget to end each line with "\n"!
For example, do this:
fragmentSource = "mov ft0, fc0\n" + "mov oc, ft0\n";
not this:
fragmentSource = "mov ft0, fc0" + "mov oc, ft0";
Forgetting the line feeds will cause really strange errors that are in no way helpful! For example: "Fragment Write All Components".
3.
Triangle Lists Only: No Triangle Strips, Fans, etc.The only supported render type is a triangle list. You can use an index buffer to mitigate the effects of this, so I don't think it will be a show-stopper. It's something to be aware of though.
4.
Cannot Render to Texture SubregionIf you are rendering to a texture, there is no way to tell it what subregion to render to; the entire texture will be used. This is a little bit of a problem for me, since I wanted to render a specific resolution to the texture. I can probably work around this by using "nearest" sampling and a larger-than-needed texture though.
ScanlinesAs far as actual progress goes, I managed to write a fragment shader that adds "scanlines" in real-time! Now, by "scanlines" I just mean alternating black horizontal lines. This is not a perfect CRT emulation, and it doesn't even look terribly good; the screen becomes much darker with all those black lines on it. It is, however, the first step
Here is the shader's code if you are interested. It's intended to run on a single fullscreen quad (pair of triangles) that has a texture stretched across it of the rendered scene. So this would run on a texture after rendering the game to that texture.
Vertex Shader// Inputs:
// va0 = vertex position
// va1 = vertex UV
//
// Ouputs:
// v0 = UV
// v1 = position in clip space
mov v0, va1
mov v1, va0
mov op, va0
Fragment Shader// Inputs:
// fs0 = The texture that the game was rendered to.
// v0 = UV
// v1 = position in clip space
// fc0.x = 2
// fc0.y = half the screen's height
tex ft0, v0, fs0<2d, nomip, nearest, clamp>
// Convert the y coordinate from clip-space to screen space and put it in ft1.x
mul ft1.x, v1.y, fc0.y
neg ft1.x, ft1.x
// Figure out if this is an odd-numbered horizontal line or not: ft1.x = y%2
div ft1.x, ft1.x, fc0.x
frc ft1.x, ft1.x
mul ft1.x, ft1.x, fc0.x
// If this is an odd-numbered line, this will turn the color black. Otherwise
// the color will be left unchanged.
mul ft0, ft0, ft1.xxxx
mov oc, ft0
Next up I need to make the phosphors glow, so hopefully I'll be making a new devlog entry soon where I discuss how awesomely well that went
Thanks goes to Somokon in
this post on the Away3D forums for the modulus technique I'm using.
If you want an excellent reference for AGAL, the official "
What is AGAL" article is perfect for the job.