I had 10 minutes & the need to do it so I added the ability to switch between using wrapped texture coordinates (default) & clamped ones.
You can just follow the way HGE_TEXTUREFILTER is done & modify it for this, but I'll stick the code here anyway.
One thing to note is I'm using a DirectX 9 flavour of Hge. I can't imagine there's any dx9-specific code here, so in theory it should work fine for dx8 Hge too...
edit: in case you're wondering what use this is, imagine you are rendering a partially-transparent texture to a quad. Some of the texture edges are coloured in, some are transparent. When the quad gets rendered with texture filtering turned on, the edges are interpolated with the opposite side, which leads to artefacts appearing along the transparent edges thanks to the inaccuracy of 32-bit floating point. Clamping the texture prevents the wrap-round, so the transparent edges are drawn correctly. You can achieve a similar result already by turning texture filtering off but then you've got the problem of having pixellated textures, unless you're going for that look.. The only downside is you lose the ability to tile the texture on a single quad.
hge.h:
1 2 3 4 5 6 7 8 9 10
/* ** HGE System state constants */ enum hgeBoolState { ... // Andy : Texture clamping HGE_TEXTURECLAMP =8, // bool clamp textures? (default: false) ... };
(if the value 8 is already being used for something else, pick another number :) )
graphics.cpp in HGE_Impl::_init_lost():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
if(bTextureFilter) { .... }
// Andy Begin : Texture clamping if(bTextureClamp) { pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP); pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP); } else { pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP); pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP); } // Andy: End
hge_impl.h:
1 2 3 4 5
// System States ... ... // Andy : Texture clamping bool bTextureClamp;
... // Andy Begin : Texture clamping case HGE_TEXTURECLAMP: if(bTextureClamp == value) { // Minor optimisation: state hasn't changed. Early-out to avoid the _render_batch() call. // this check isn't done for HGE_TEXTUREFILTER. Hint hint ;) return; } bTextureClamp = value; if(pD3DDevice) { _render_batch(); if(bTextureClamp) { pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP); pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP); } else { pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP); pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP); } } break; // Andy End
System.cpp in HGE_Impl::System_GetStateBool:
1 2 3
... // Andy : Texture clamping case HGE_TEXTURECLAMP:return bTextureClamp;
Ok, there are some improvements that could be made here. First off I'm not too keen on the duplication of code, that could be moved into a function (my reasons for not doing so: the rest of hge isn't done this way, & I was feeling too lazy to do the plumbing-in. Maybe later.). Additionally there's a whole host of other sampler states that could be set, though this would require an enumeration/integer implementation.
or... // render something hge->System_SetState( HGE_TEXTURECLAMP, true ); // clamp the texture // render something that needs a clamped texture hge->System_SetState( HGE_TEXTURECLAMP, false ); // back to default. // render something else
You can use this at any point in the rendering pipeline - either at initialisation or within the framefunc (for individual objects), same as HGE_TEXTUREFILTER. As with the texture filtering, an additional _render_batch() call is made every time the state is changed, so if you intend to switch between the two modes regularly it's worth ordering your geometry to keep the state changes to a minimum.
This doesn't appear to work with an unaltered HGE source code. It appears that ->SetSampleState does not appear in DX8, or the constants D3DSAMP_ADDRESSU and D3DSAMP_ADDRESSV.
I'm not familiar with DirectX (one of the reasons I'm using a 3rd party graphics engine to begin with), so can you suggest any workarounds? Alternately, what is involved in bringing HGE up to DX9?
Lol apologies for this, I guess it's entirely dx9 specific code :)
There's no point in switching to DX9 just so you can clamp your textures. DX8 will be able to handle it. According to http://msdn.microsoft.com/en-us/library/bb204851%28VS.85%29.aspx you should be able to use SetTextureStageState instead. It also mentions the 'D3DSAMP_' prefix - you should be able to remove that part from the constant names to get it compiling.