• Advertisement
Sign in to follow this  

[DX9/PS 1.4] Clipping Text/Sprites

This topic is 2676 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is it possible to clip text using a pixel shader, allowing one to not have to break batches to call ScissorRect?

My problem is how to pass the clipping rect and then process it. (I seem to have problems swizzling under HLSL with ps 1.4 and problems using "if"'s).

I would assume that to clip it, I would just call clip(-1)? or can this be optimized to some thing better like clip(Out.Pos.x - rect.x)?

I'm using an FVF of (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) for the text at the moment if that helps any, but I'm trying to move away from using the FFP.

Share this post


Link to post
Share on other sites
Advertisement
HLSL is useful with shader model 3.0 and up. Pixel shader 1.4 may have too little register space for not being optimized by hand. If PS 1.4 is enough, Input.vPosition.xy should be the 2D screen position in pixels from the upper left corner. One float4 in the global constant buffer can be the rectangle (minX, maxX, minY, maxY).

This might work:

#define MINX Rect.x
#define MAXX Rect.y
#define MINY Rect.z
#define MAXY Rect.w
clip(Input.vPosition.x - MINX);
clip(MAXX - Input.vPosition.x);
clip(Input.vPosition.y - MINY);
clip(MAXY - Input.vPosition.y);

Share this post


Link to post
Share on other sites
Thanks for the reply :)

ok, so I managed to get something working at last, just as a test. however, how do I get screen space coords(ie: 0,0 to screen_width,screen_height) or do I have to preconvert the clipping coords to [0..1]?

trying to use VPOS gives me compile errors. my 'current' simple(fixed clipping values) pixel shader(working)

sampler2D Tex0;

float4 ps_main(float4 UV : TEXCOORD0) : COLOR0
{
clip(UV.x - .5);
return tex2D(Tex0,UV) * float4(UV.x,UV.y,0.5,UV.y); //add a little color to make the borders stand out
}





and the non-working one, trying to use screen space with VPOS
float4 ps_main(float4 vPos : VPOS, float4 UV : TEXCOORD0) : COLOR0
{
clip(vPos.x - 200);
return tex2D(Tex0,UV) * float4(UV.x,UV.y,0.5,UV.y);
}






EDIT: figured out why VPOS doesn't work, its fo PS 3.0 :( (the note about that is hidden away on MSDN...). it does mention using POSITION, but I get problems accessing components if I use POSITION. And seeing as I omitted this before, the VS just does a simple text pass through and applies the WVP transform the the vertices, returning both POSITION & TEXCOORD0

Share this post


Link to post
Share on other sites
Hmmmm, your thread made experiment with and google for clip(), and then I found this. Obviously, clip will not improve performance, pixels are still processed, even if not drawn.

Might not be a problem, cause your main intention was to keep your batch "in one piece" (i.e. no render-state change). When I started DX and approached a 2D-axis-aligned clipping with scissor-rect, I experienced the same performance drop. So here is my solution to this, which might be of use for you: I clip the rectangles on the CPU-side (intersection of rectangles) and even omit the non-intersecting ones. In the process I adjust the tex-coords accordingly. I think this could even be done in a vertex shader, haven't tried yet. It's quite fast already. Drawback beeing: Needs dynamic vertex buffer and of course only applies to axis-aligned rectangles (though text normally is).

Share this post


Link to post
Share on other sites
Quote:
Original post by unbird
Might not be a problem, cause your main intention was to keep your batch "in one piece" (i.e. no render-state change). When I started DX and approached a 2D-axis-aligned clipping with scissor-rect, I experienced the same performance drop. So here is my solution to this, which might be of use for you: I clip the rectangles on the CPU-side (intersection of rectangles) and even omit the non-intersecting ones. In the process I adjust the tex-coords accordingly. I think this could even be done in a vertex shader, haven't tried yet. It's quite fast already. Drawback beeing: Needs dynamic vertex buffer and of course only applies to axis-aligned rectangles (though text normally is).
was trying to avoid extra CPU work, but this appears to be the best solution, my concerns is what happens if you clip the texture to an odd boundery(ie: the division of the end text coords ends up in the middle of a texel), does it round down or up?

Just out of interest, I managed to get farther with the PS clipping, thanks to something MJP posted on the XNA forums:
sampler2D Tex0;

float4 ps_main(float4 UV : TEXCOORD0, float3 vPos : TEXCOORD1) : COLOR0
{
clip(vPos.x - 32);
return tex2D(Tex0,UV) * float4(vPos.x,vPos.y,1,1);
}

struct VS_INPUT
{
float4 Position : POSITION;
float2 Texture : TEXCOORD0;
};

struct VS_OUTPUT
{
float4 Position : POSITION;
float2 Texture : TEXCOORD0;
float3 vPos : TEXCOORD1;
};


float4x4 WorldViewProj;

VS_OUTPUT vs_main(in VS_INPUT In)
{
VS_OUTPUT Out;
Out.Position = In.Position * WorldViewProj;
Out.Texture = In.Texture;
Out.vPos.xyz = Out.Position.xyz;
return Out;
}


the problem I ran into was any use of .w must be done in the vs(the ps compiler moans about access to .w), but dividing .xyz by .w didn't seem to yeild screen space coords, but the original .xyz values don't appear to be screen space(post transform)

Share this post


Link to post
Share on other sites
Quote:
was trying to avoid extra CPU work, but this appears to be the best solution, my concerns is what happens if you clip the texture to an odd boundery(ie: the division of the end text coords ends up in the middle of a texel), does it round down or up?
Are you concerned about pixel-perfect drawing of text ? Admittedly, haven't thought of this yet: My variant uses linear filtering, but you, as I understand, probably want point-filtering (and of course Directly Mapping Texels to Pixels), at least for text. If you are concerned about rounding, clamp/round manually, e.g. add/subtract 0.5 and cast to int in pixel coords and calculate the texcoord only afterwards. Haven't tried myself, but that's probably the way if you got artifacts.
Quote:
the problem I ran into was any use of .w must be done in the vs(the ps compiler moans about access to .w), but dividing .xyz by .w didn't seem to yeild screen space coords, but the original .xyz values don't appear to be screen space(post transform)
I haven't done (much) 3D yet, but from what I hear the /w only makes sense with perspective transformation. And assuming you got a ortho-projection, propagating the screen (pixel) coordinates is IMHO rather
   Out.vPos.xyz = In.Position.xyz   
i.e. just a copy or maybe a offset.

Edit: Sorry for the confusion. You use a WorldViewProjection, so it really depends how your transformations look. If the world part is identity (object-to-world) my simple propagation should be correct, otherwise Out.vPos is something like mul(In.Position, World). If you need more help here, show us your transformation setup and describe what you are rendering. I suspect there's a difference whether you render text ("screen-coordinates") or sprites (is there a 2D-camera ?). Screenshots are also an option.

[Edited by - unbird on October 23, 2010 1:15:13 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement