CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
struct v2f
{
float4 pos : SV_POSITION;
float3 color : COLOR0;
float2 uv : TEXCOORD0;
};
float4 _MainTex_ST;
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
return o;
}
float4 frag (v2f i) : COLOR
{
float4 pix = tex2D(_MainTex, i.uv);
float r = pix.r;
float g = pix.g;
float b = pix.b;
// the stuff below obviously doesnt work...
// but the general idea is to split the texture up by channel and put it all back into a single texture ("the output")
return float4(
r,
r, // should be something like the red value of the next pixel and so on..
r, // should be something like the red value of the next pixel after and so on..
1f
);
return float4(
g,
g, // should be something like the green value of the next pixel and so on..
g, // should be something like the green value of the next pixel after and so on..
1f
);
return float4(
b,
b, // should be something like the blue value of the next pixel and so on..
b, // should be something like the blue value of the next pixel after and so on..
1f
);
// i'm stuck
}
ENDCG
You’d think something like this has been done before… either it has and i’m really bad at searching or it hasn’t and now is your chance to shine.
I’m not entirely sure that it’s possible… or even really what you’re trying to achieve.
You’d ideally need to know the resolution of the texture and then multisample UV coords 1 pixel across and down each time? Which, for a 1024 texture would be an infeasible amount of instructions.
Going by your example ascii-art image, what happens when you have more than 4x4 pixels?
The reason you probably can’t find an existing shader for this is that planar image formats are unheard of in real-time rendering. Graphics cards are designed almost entirely around the four-component vectors that represent RGBA, and as such there are a few things that will get in your way.
A fragment shader can take multiple texture samples, but only output a single RGBA value. This is called a “gather” operation rather than what you’re trying to do, which is to “scatter”.
Graphics cards are generally not what you use in order to do texture processing when you are sending the results back to a file. The CPU will always do the actual arrangement of bytes and writing to disk.
What is your desired output? An image file with a planar format? What do you plan to use it for?
You could do it but only if you calculate 4 outputs at once in a single shader, then only output one of the four color components swizzled together based on a vertical modulo of 4 lines, based off the fragment coordinate. ie a) calculate 4 outputs, b) figure out what row you’re on and the modulo ie fragment coordinate’s Y coordinate mod 4 (fmod?). … then c) do an if/else to output like float4(color1.r,color2.r,color3.r,color4.r) if its the red row, etc.
More pixels means larger arrays of collected red green and blue and alpha channels (although the alpha can be ignored) currently i’m working with full hd 1920x1080 which is a good bundle of pixels indeed, but in the end the way to achieve this should be independent of the resolution. The resolution just determines the eventual size of the resulting arrays of pixels. To expand on my ASCII Art 5x6 (30) RGBA packed pixels has a result of the following order 30 R values then 30 G values then 30 B then the 30 A… the concept of a planar texture
I get what your saying and indeed if i was writing to a file cpu would be the way to go, only i’m writing the texture data back to a surface on the videocard in preparation for encoding by a chip on the video card (end result is an H264 stream at 30fps).
Secretly i’m not doing RGB but storing YUV data in the RGB texture (rgb is a more common term in this world) but the yuv data is irrelevant in this question.
I have the whole process working it just needs a little speed boost currently i’m letting the cpu split the channels up post render per pixel in a native plugin. It would be faster if the render was already in a planar order letting me just copy the data to its dest, thus not needing to to go past each pixel for every frame.
I like what your saying and it sounds like it’s feasible would it be faster than the cpu? Plus I’m not the best mathematician out there so creating this wouldn’t be an easy task for me. Any chance you can pseudo shader code this?