c++ - Precise Texture Overlay -
i'm trying set two-stage render of objects in 3d engine i'm working on written in c++ directx9 facilitate transparency (and other things). thought working nicely until noticed dodgyness on edge of objects rendered before objects using 2 stage method.
the 2 stage method simple:
draw model off-screen ("side") texture of same size using same zbuffer (no msaa used anywhere)
draw off-screen ("side") texture on top of main render target suitable blend , no alpha test or write
in image below left view 2 stage render of gray object (a lamppost) body in-front of rendered directly target texture. right view two-stage render disabled, both rendered directly onto target surface.
on close inspection if side texture offset 1 pixel "down" , 1 pixel "right" when rendered on target surface (but rendered correctly in-place). can seen in overlay of off screen texture (which program write out bitmap file via d3dxsavetexturetofile
) on screen shot below.
one last image can see edge in side texture coming (it's because rendering side texture does use z test). left screen short, right side texture (as overlaid above).
all leads me believe "overlaying" isn't effective. code renders side texture on main render target shown below (note same viewport used scene rendering (on , off screen)). "effect" object instance of thin wrapper on lpd3dxeffect
, "effect" field (sorry shoddy naming) being lpd3dxeffect
itself.
void drawsideover(lpdirect3ddevice9 dxdevice, drawdata* ddat) { // "ddat" drawdata contains lots of render state information, need here handles targetsurface , sidesurface d3dxmatrix idmat; d3dxmatrixidentity(&idmat); // create identity matrix dxdevice->setrendertarget(0, ddat->targetsurface); // switch targetsurface dxdevice->setrenderstate(d3drs_zenable, false); // disable z test , z write dxdevice->setrenderstate(d3drs_zwriteenable, false); vertexover oververts[4]; // create square oververts[0] = vertexover(-1, -1, 0, 0, 1); oververts[1] = vertexover(-1, 1, 0, 0, 0); oververts[2] = vertexover(1, -1, 0, 1, 1); oververts[3] = vertexover(1, 1, 0, 1, 0); effect.settexture(ddat->sidetex); // use side texture shader texture ("tex") effect.effect->settechnique("over"); // change "over" technique effect.setviewproj(&idmat); // set viewproj identity matrix 1/-1 map directly effect.effect->commitchanges(); setalpha(dxdevice); // sets alpha blending works fine uint numpasses, pass; effect.effect->begin(&numpasses, 0); effect.effect->beginpass(0); dxdevice->setvertexdeclaration(vertexdecover); dxdevice->drawprimitiveup(d3dpt_trianglestrip, 2, oververts, sizeof(vertexover)); effect.effect->endpass(); effect.effect->end(); dxdevice->setrenderstate(d3drs_zenable, true); // revert these don't mess drawn after dxdevice->setrenderstate(d3drs_zwriteenable, true); }
the c++ side definition vertexover struct , constructor (hlsl side shown below somewhere):
struct vertexover { public: float x; float y; float z; float w; float tu; float tv; vertexover() { } vertexover(float xn, float yn, float zn, float tun, float tvn) { x = xn; y = yn; z = zn; w = 1.0; tu = tun; tv = tvn; } };
inefficiency in re-creating , passing vertices down gpu each draw aside, want know why method doesn't quite work, , if there are better methods overlaying textures alpha blend won't exhibit issue
i figured texture sampling may matter in matter, messing options didn't seem (for example, using linear filter makes fuzzy might expect implying offset isn't clear-cut 1 pixel discrepancy). shader code:
struct vs_input_over { float4 pos : position0; float2 txc : texcoord0; }; struct vs_output_over { float4 pos : position0; float2 txc : texcoord0; float4 altpos : texcoord1; }; struct ps_output { float4 col : color0; }; texture tex; sampler texsampler = sampler_state { texture = <tex>;magfilter = none; minfilter = none; mipfilter = none; addressu = mirror; addressv = mirror;}; // side/over shaders (these make "over" technique (pixel shader version 2.0) vs_output_over vshade_over(vs_input_over inp) { vs_output_over outp = (vs_output_over)0; outp.pos = mul(inp.pos, viewproj); outp.altpos = outp.pos; outp.txc = inp.txc; return outp; } ps_output pshade_over(vs_output_over inp) { ps_output outp = (ps_output)0; outp.col = tex2d(texsampler, inp.txc); return outp; }
i've looked "blended blit" or can't find anything, , other related searches have brought forums implying rendering quad orthographic projection way go doing this.
sorry if i've given far detail issue it's both interesting , infuriating , feedback appreciated.
it looks me problem mapping of texels pixels. must offset screen-aligned quad half pixel match texels direct screenpixels. issue explaines here: directly mapping texels pixels (msdn)
Comments
Post a Comment