/*
==========================================================================================
Cg Acceleration Research
Edgar Velázquez Armendáriz - edgar [at] graphics [dot] cornell [dot] edu
------------------------------------------------------------------------------------------
pointProjection.cg
Point cloud projection shaders using MRT. Requires fp40 profile.
==========================================================================================
*/
/* Vertex information to be transfered */
struct vertexInfo {
float4 pos : POSITION;
half2 uv : TEXCOORD0;
half4 color : COLOR0;
half4 colorSec : COLOR1;
half2 subPixel;
};
// vp40: # 18 instructions, 2 R-regs
void vertMain( uniform float4x4 ModelViewProj : state.matrix.mvp,
uniform half2 c, // Vector <width/2, height/2> for subpixel transformation
in vertexInfo IN,
out vertexInfo OUT ) {
// Transformed position of the vertex into clip coordinates
OUT.pos = mul(ModelViewProj, IN.pos);
// Force points into clipping plane, to avoid the backgroud points to be
// deleted by the depth cull
OUT.pos.z = clamp(OUT.pos.z, -1e38, OUT.pos.w * (0.999999523162841796875));
// Just copy the input color, and the secondary color which contains the encoded pointID
OUT.color = IN.color;
OUT.colorSec = IN.colorSec;
// The rectangle texture coordinates encode the index of the vertex into the
// original array of data, in such a way that all its original data is read from
// the packed texture
OUT.uv = IN.uv;
// Get the pixel mapping, integer and fractional part (characteristic and mantissa)
const half2 gamma = c * OUT.pos.xy / OUT.pos.w + c;
// The fractional part is stored in a varying parameter:
// Each mantissa will give me the information about subpixel location
OUT.subPixel = frac(gamma);
OUT.subPixel.y = 1 - OUT.subPixel.y; // Calculated with origin on bottom left corner, It must
// be in the upper left corner.
}
// fp40: # 15 instructions, 1 R-regs, 1 H-regs
void fragMain( uniform samplerRECT packData : TEXUNIT0,
in vertexInfo IN,
in float3 pos : WPOS,
out float depth : DEPTH,
out half4 outputs[3] : COLOR0 ) {
// UPDATE TO REFLECT CHANGES IN ENVIRONMENT
const half MAX_AGE = 255; // [0,255]
const half FLAGS = 64; // [0,255] // FLAGS == 0x40
// After the texture operation, do some math to cover the latency
half4 idAgePacked = texRECT(packData, IN.uv);
// Subpixel info
half2 subPixV = floor(half2(4,4) * IN.subPixel);
half subPix = 1/255.0h * (4*subPixV.y + subPixV.x); // subPix (not scaled) is in the range [0, 15]
// The secondary color contains the pointID, with the LSB in R and the MSB in B, so I just
// need to copy that information
half4 idVertex = half4(FLAGS/255.0, IN.colorSec.rgb);
// If this is an invalid point, because of the age, discard
if (idAgePacked.r >= MAX_AGE/255.0h) { outputs[0] = half4(1,0,0, subPix); }//discard; }
// Normal color, it also copies the subpixel info into the final RGBA texture,
// ready to be attached to the EPI-GPU.
outputs[0] = half4(IN.color.rgb, subPix);
// The final output contains the Flags in R and the pointID splitted in GBA
outputs[1] = idVertex;
// In the third render buffer, I will store:
// r - Priority
// g - seqnum
// b - flags/seqnum info
// a - 0 as flag -> invalid pixels have a = 1
half priority = saturate(idAgePacked.r/2.0 - 8/255.0); // priority = max(0,age-16) / 2
outputs[2] = half4(priority, IN.color.a, 1/255.0h * FLAGS + IN.color.a, 0);
}