tags:

views:

218

answers:

1

Given a destination rectangle and an x/y offset value, I need an image to be drawn within the confines of that destination rectangle. If the offset would push the image off the edge of the rectangle, then the part that "pushes out" should appear on the opposite side of the destination rectangle. In simplest terms, I need a scrolling background.

In GDI, I can accomplish this with an "ImageAttributes" object that uses a tile wrap mode:

ImageAttributes attributes = new ImageAttributes();
attributes.SetWrapMode(System.Drawing.Drawing2D.WrapMode.Tile);

Rectangle rectangle = new Rectangle(0, 0, (int)width, (int)height);
g.DrawImage(bmp, rectangle, -x, -y, width, height, GraphicsUnit.Pixel, attributes);

Now, I need a way to do this in DirectX. Assume that this is the method I have right now:

public void RenderTexture(PrismDXObject obj, D3D.Texture texture, int xOffset, int yOffset)
{
    if (obj != null && texture != null)
    {
        _renderSprite.Begin(D3D.SpriteFlags.AlphaBlend);
        _renderSprite.Draw(texture,
            new Rectangle(0, 0, (int)obj.Width, (int)obj.Height),
            new Vector3(0.0f, 0.0f, 0.0f),
            new Vector3((int)obj.Left, (int)obj.Top, 0.0f),
            obj.RenderColor);
            _renderSprite.End();
        }
    }
}

...where "_renderSprite" is a D3D.Sprite, and PrismDXObject is a simple class that stores x/y/width/height/color. How can I update this method so that xOffset and yOffset can be used to make the texture wrap? Remember, my end-goal is a scrolling background that loops as the player walks forward.

Incidentally, that RenderTexture() method is meant to be a "library method" which can be called from anywhere in my program... so if I'm doing something really inefficient or ill-advised, I'd welcome a friendly warning! My main concern is getting the wrapping background to work, though.

A: 

I'm not sure that the sprite mechanism allows for what I'm about to explain, but 2 triangles certainly do. If this does not work with sprites, use triangles directly:

What you're asking for is directly supported by the texturing subsystem, it is called texture wrapping.

  • When you specify the texture coordinates that your quad will use, instead of using the 0,0-1,1 range, you can use 0+xoffset/tex_x_size, 0+yoffset/tex_y_size, 1+xoffset/tex_x_size, 1+yoffset/tex_y_size for your texture coordinates.
  • Then, the only thing left to do is to specify that the texture sampler you will use to map your background does texture wrapping. To do this, you need to set to D3DTADDRESS_WRAP the D3DSAMP_ADDRESSU and D3DSAMP_ADDRESSV sampler states. Note, this is the default for the sampler state.

that's it. Now, getting back to D3D.Sprite specifically, the Draw method takes a rectangle that tells which part of the texture to use. have you tried drawing xoffset, yoffset, xOffset+obj,Width, yoffset+obj.height ? This will only work if the sprite subsystem uses a sampler that has wrapping on, and I don't know how sprite is implemented internally.

Bahbar
I like this idea... it didn't work yet; I might need some clarification:1) I did a _graphics.GetSamplerStageStateInt32() call for D3D.SamplerStageStates.AddressU and D3D.SamplerStageStates.AddressV, and I got back a value of 1 for each of them. Does this mean that they are already set (as per default)?2) If so, I'm wondering if I should just use 2 triangles for rendering the background, instead of my "universal" sprite that renders everything else. If so, I'll need to do a little research on how to use triangles, since I've only ever used sprites!Thanks for your helpful reply so far!
Professor Mustard
1) yep, 1 is indeed Wrap. See http://msdn.microsoft.com/en-us/library/ms858163.aspx2) I don't know for sure how sprite maps textures. what result did you get with the above method ? Understanding all the triangle stuff will require some investment on your part if you've never looked at them. Good luck!
Bahbar
The result I got with sprites was curious... the image was shoved the expected number of pixels, but it was cropped instead of wrapped... and stranger still, the transparent parts of the texture were rendered in solid black. I will look into using triangles, although I'm still unclear as to the intended purpose of triangles vs sprites (for example, why you would use one over the other). Thanks for your input!
Professor Mustard
Well, DirectX is first and foremost a 3D API. Internally, it pretty much only deals with triangles, lines and points. your Sprites are a layer built on top of it, and it uses it's own means to mimic what 2D APIs call sprites (typically by drawing 2 screen-aligned triangles per sprite). if you want to use DirectX, you probably do want to learn about triangles.
Bahbar