# Blting DX9 textures to GDI, editing, and blting back

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

## Recommended Posts

I'm looking for info on directly editing height and splat map data. My initial thought was that GDI with it's premade brushes would be an asset. So I set about learning what i needed from GDI to get the DXTexture into an HDC for use in a window.I've used BltBit which copies the entire Pixels RGB data from the dx surface into the HDC of my window.

I would prefer to copy a single SRC channel ( R,G,B,or A for the splat layers(1-4)), leaving the rest of the DST bitmap black. After a brush has affected the bitmap, I intend to copy the single channel back to the initial DXTexture, which is used as a splat map in my terrain viewer(hopefully editor)

Another thought was skipping GDI directly, and and implementing brushes in DX(unless they exist in an area i'm not familiar with) using pixel shaders, and modifying textures directly that way.

I'd appreciate a nudge in the right direction, if anyone has a spare moment.

##### Share on other sites

I would prefer to copy a single SRC channel ( R,G,B,or A for the splat layers(1-4)), leaving the rest of the DST bitmap black.

Can you describe a little better what you want to do, rather than how you want to do it? E.g., it's not clear what you mean by SRC and DEST, a black bitmap, etc.

(Without knowing exactly what you're trying to achieve) Have you thought about render-to-texture?

##### Share on other sites

Sorry for the late response, I guess my previous reply never got posted. I'm trying to edit heightmap map and splat map data. SRC and DEST, are the source and destination bitmaps in the bitblt function.

I think render to texture would work, It would be easy enough just to create a shader that allows a mask as a float4 input, and write out and individual channel to the windows HDC so that i can see them.

But then how does one go about making brushes in DX?

I would assume I'd need to pick the spot under a mouse click, and draw a quad with the brush texture, multiplying by the channel mask onto the splatmap ?

##### Share on other sites

I'm trying to edit heightmap map and splat map data.

Okay. Good start, but a bit too general. So..

Can you describe a little better what you want to do, rather than how you want to do it?

You appear to be locked in on doing something with "brushes" but it's not clear what you actually want to do.

how does one go about making brushes in DX?

Dx9 doesn't support GDI-like brushes. This doesn't respond to your question directly, but GDI+ does support alpha textures.

If, as asked above, you could describe what you'd like to accomplish, a bit more detailed than "edit a heightmap" but not locked into a specific method, maybe someone could help you more.

##### Share on other sites

The easiest way to do this is to use 4 separate single channel textures in your editor, and combine/compress them as a final step. Texture arrays are ideal for things like this.

The brushes can be easily created mathematically on the GPU, or using GDI+ (which has shape commands). You'll need a fifth single channel texture the to use as a destination channel - copy one channel to it entirely and then add/subtract/multiply blend with your brush texture.

Finally, seeing as you're only using 4 textures, you might want to consider have a fifth default texture that's applied to the entire world, and then blend the other 4 depending on your splat texture. You can do something nifty here - use a rock/cliff face texture with tri-planar texturing, and don't overpaint it with the other 4 textures on the steeper areas.

Edited by mark ds

##### Share on other sites

Can you describe a little better what you want to do, rather than how you want to do it?

You appear to be locked in on doing something with "brushes" but it's not clear what you actually want to do.

how does one go about making brushes in DX?

Dx9 doesn't support GDI-like brushes. This doesn't respond to your question directly, but GDI+ does support alpha textures.

If, as asked above, you could describe what you'd like to accomplish, a bit more detailed than "edit a heightmap" but not locked into a specific method, maybe someone could help you more.

I just want to be able to paint the terrain by hand essentially. i don't know how to be more clear on that?

this is exactly the functionality i want to achieve.

Edited by Burnt_Fyr

##### Share on other sites

The easiest way to do this is to use 4 separate single channel textures in your editor, and combine/compress them as a final step. Texture arrays are ideal for things like this.

The brushes can be easily created mathematically on the GPU, or using GDI+ (which has shape commands). You'll need a fifth single channel texture the to use as a destination channel - copy one channel to it entirely and then add/subtract/multiply blend with your brush texture.

Finally, seeing as you're only using 4 textures, you might want to consider have a fifth default texture that's applied to the entire world, and then blend the other 4 depending on your splat texture. You can do something nifty here - use a rock/cliff face texture with tri-planar texturing, and don't overpaint it with the other 4 textures on the steeper areas.

1) well if everything is done in a shader, than writing the individual channels won't be an issue, likely.

2) I think these extra channels and binding will not be needed? if I create a single render target texture, and use that to load the splat map on file->open, than i can pass a channel mask as a shader constant, allowing direct editing of each channel.

3) I'm not sure how many splats is common for a modern terrain system, but I think it would depend a lot on the size of chunks. I started with 4, because i was just going from my own thoughts(4 channels, 4 maps) but have added a 5th base texture already. Since it is default everywhere, it had no real bearing on this thead, so i neglected to mention it. But since you did, I was/am having issues when i try and visuallize just the default texture. rather than a plain dirt terrain, the ps seems to map the splat map onto the terrain. rather than the default one.

float4 splatmap = tex2D(splatmaptexsampler,float2(input.Texcoords.x , input.Texcoords.z ));

float4 base   = tex2D(basetexsampler,   float2(input.Texcoords.x * 10, input.Texcoords.z * 10));
float4 splat1 = tex2D(splat1texsampler, float2(input.Texcoords.x * 10, input.Texcoords.z * 10));
float4 splat2 = tex2D(splat2texsampler, float2(input.Texcoords.x * 20, input.Texcoords.z * 20));
float4 splat3 = tex2D(splat3texsampler, float2(input.Texcoords.x * 10, input.Texcoords.z * 110));
float4 splat4 = tex2D(splat4texsampler, float2(input.Texcoords.x * 5, input.Texcoords.z * 5));

result =  base;


how ever, if result is a combination of base and one or more of the splats, then every thing appears ok. I assume this is because if i don't use the splatmap in the final calculations, the shader ignores it, and it's sampler. meaning that the next sampler created (basetexsampler) gets set to the stage 0 rather than stage 1.

result = float4(base.xyz,0) * (1 - splatmap.r) + (splat1 * splatmap.r);


edit: ignore the magic numbers in the PS, those scales will be passed in as constants as well, but I'm not going to fix that until i have this painting sorted.

Edited by Burnt_Fyr

##### Share on other sites

If you're restricted to DX9, then you have no choice but to use an extra channel to write your output to - you simply can't read/write to/from the same texture. You can in DX11, http://msdn.microsoft.com/en-us/library/ff728749(v=vs.85).aspx, but it not as simple as you might assume.

If you're able to use DX10, use texture arrays to avoid unnecessary bindings.

As for the number of splats, I believe elder scrolls games for example (which are pretty much classic terrain renderers) allow for 6 unique textures per "cell". This makes sense because if you DXT compress the splat maps, an RGBA takes up twice the memory as an RGB - it's just as memory efficient to have two RGB (6 textures), plus an optional base texture, as it is to have 4 + base.

##### Share on other sites

If you're restricted to DX9, then you have no choice but to use an extra channel to write your output to - you simply can't read/write to/from the same texture. You can in DX11, http://msdn.microsoft.com/en-us/library/ff728749(v=vs.85).aspx, but it not as simple as you might assume.

If you're able to use DX10, use texture arrays to avoid unnecessary bindings.

As for the number of splats, I believe elder scrolls games for example (which are pretty much classic terrain renderers) allow for 6 unique textures per "cell". This makes sense because if you DXT compress the splat maps, an RGBA takes up twice the memory as an RGB - it's just as memory efficient to have two RGB (6 textures), plus an optional base texture, as it is to have 4 + base.

I see what you mean yes, i was thinking i'd do separate passes, but now i see the error in that logic. so you are suggesting R,G,B,A and a bounce texture. and on draw i should  read the chaneel i'm editing, draw to the bounce texture, and then blit the results back to the original channel if i get you correctly? Can you elaborate on the RGB vs RGBA with regards to compression?.

The easiest way to do this is to use 4 separate single channel textures in your editor, and combine/compress them as a final step. Texture arrays are ideal for things like this.

The brushes can be easily created mathematically on the GPU, or using GDI+ (which has shape commands). You'll need a fifth single channel texture the to use as a destination channel - copy one channel to it entirely and then add/subtract/multiply blend with your brush texture.

Finally, seeing as you're only using 4 textures, you might want to consider have a fifth default texture that's applied to the entire world, and then blend the other 4 depending on your splat texture. You can do something nifty here - use a rock/cliff face texture with tri-planar texturing, and don't overpaint it with the other 4 textures on the steeper areas.

##### Share on other sites

Here's what I would do:

1: Unproject the mouse from screen space to find the point on the terrain where it touches (the are plenty of resources to do this - search for terrain picking or similar)

2: Render a quad, the size of you brush, to the 'bounce' texture. To do this, you need to multi-texture the quad using the full extents of the brush, and the sub-region from the splat channel centred around the mouse selection point. In the pixel shader you can then add, subtract or multiply (etc.) the two textures to achieve the desired effect.

3: Copy the newly modified region from the bounce texture back to the original splat channel.

4: Redraw scene!

The great thing is that this technique works for both heightmap editing, and splat channel editing - the only real difference is that you'll use more bits in the heightmap texture & brush than the splat map (16/32 bits vs 8).

With respect to compression, the splat maps, once finished, can normally be compressed to a DXT format without significant loss of details. However, an RBG DXT1 compresses to 64 bits per 4x4 pixel block, whereas an RGBA DXT3 will require 128 bits per 4x4 block. So, for the same storage requirements, you can use two RGB DXT1 textures (6 splat channels) for the price of a single RGBA DXT3 textures (4 channels). It simply allows for more texture variability for a given amount of storage. Obviously this will necessitate more work in the editor to take into account the extra channels, but it's not really a big deal.

Incidentally, are you limited to DX9?

Edited by mark ds

1. 1
2. 2
3. 3
Rutin
18
4. 4
JoeJ
14
5. 5

• 14
• 10
• 23
• 9
• 34
• ### Forum Statistics

• Total Topics
632634
• Total Posts
3007548
• ### Who's Online (See full list)

There are no registered users currently online

×