Surfaces and Textures

Started by
11 comments, last by Darkneon 18 years, 8 months ago
Hi all, So I'm reading Chapter 10 - Rendering to Surfaces from DirectX 9 Kick Start. Like the title suggests, the author is drawing the main view to a surface and then displays it. But no matter how many times I re-read it or analyze the code, I don't understand him. He's creating an empty texture and a surface which is retrieved from the texture. Then, he draws on the surface. I paraphrase him, 'since the surface is derived from the texture, it's like drawing on the texture', he says. Then, he uses a sprite object to render the texture on the screen. OK. I don't get what is the difference between a surface and a texture. It's funny because I find he refers to them interchangeably. Still, he uses each one differently. But what I really don't get is why doesn't he just draw to the texture directly? What does the surface bring to the texture? Fill me in, please.
Advertisement
A texture is a collection of one or more surfaces which can be used to skin triangles. A surface is closer to a raw bitmap object. You do not write directly to a texture because it could have multiple mip map levels, so you have to specificy which level you are interested in, then you can get the surface for that level and modify it. Of course, if you are actually modifying any level by hand in the first place, it is most likely the first and only level, but there is no rule that says it has to be. So basically, textures are what are used as input in the rendering pipeline, but they contain surfaces which can be edited. Hopefully that helps a little.
Thanks for trying Mumpo, but they still look the same to me.

Quote:A texture is a collection of one or more surfaces

Lets say I assign 3 surfaces to a texture, and I load a different image for each of them. What will this give me? When I come to apply the texture to my triangle, I can switch between the different surfaces? Then, why not just create 3 textures and switch between them?

Quote:they contain surfaces which can be edited

This is really confusing because in a earlier chapter, the author was writing directly to the texture (he never mentioned the word surface). Here's what he did. He locked the texture, and stored the pointer to that texture. Looped through the width and height, and changed the color of each pixel. Unlocked the texture at the end. He used the LockRectange() function from the Texture class.
If you look carefully he probably either locked a surface, or he locked a texture, to get the surface in the texture, notice the second function below has a level parameter, that's for which surface (in the texture), is being got.

Locking a surface;
HRESULT LockRect(D3DLOCKED_RECT *pLockedRect,
const RECT *pRect,
DWORD Flags
);

Locking a texture, but actually getting the surface in the texture;
HRESULT LockRect(UINT Level,
D3DLOCKED_RECT *pLockedRect,
CONST RECT *pRect,
DWORD Flags
);

You have to think about the main uses for textures and surfaces, textures are for 3d stuff, so that mipmaps can be used. Surface 0, is the same size as the actual texture (the size of the bitmap you loaded), then each level the size shrinks by half, in 3d these are automatticaly changed depending how far away from the object you are.

Surfaces, though can be used for 2d stuff (although 3d quads are still probably better for this), if you are doing 2d stuff (either in 3d quads), or 2d you can create a texture, and say how many surfaces you want for it, either 1 or 0, (0 means 1 surface,(no extra mipmap levels) I think), then as your book showed you, you can either get the surface, or get the texture (surface in the texture).

An easy way to think of textures and surfaces, is maybe that a texture is like a struct, containing up to 8 surfaces, and you can use as many or few of them as you want.


OK Stevieboy, I think I got it :)

So, a texture is just a bunch of surfaces that are half in width and height than the previous one? But, when you say that a texture can have up to 8 surfaces, do you mean 8 different surfaces with their mipmaps. Or that the texture can have up to 8 mipmaps(1 mipmap = 1 surface)?

I think you were right on about locking the texture and getting the surface. Here's the line of code that the author uses (Managed DirectX + C#).

uint* pData = (uint*)t.LockRectangle(0,LockFlags.None).InternalData.ToPointer();


The 0 is a level, I assume it's the level of the surface. t is the texture obejct.

One last thing, what happens to the mipmaps when you edit the surface (any level). The way you guys explained it is if I change one then it does not affect the mipmaps. I just run the example making the mesh going away from the camera, and the surfaces where still being modified. Although, in the code he always modifies level 0. So is DirectX really recreating the mipmaps at each frame?

Thanks

Darkneon
Quote:So, a texture is just a bunch of surfaces that are half in width and height than the previous one? But, when you say that a texture can have up to 8 surfaces, do you mean 8 different surfaces with their mipmaps. Or that the texture can have up to 8 mipmaps(1 mipmap = 1 surface)?


I think textures can have any number of mipmaps. For example, if you're using a 1024x1024 texture, it will have 11 mipmaps: 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, and 1. Each mipmap level is stored in its own surface inside the texture, starting at surface 0 with the full-size (1024) mipmap, and counting up from there.

Quote:One last thing, what happens to the mipmaps when you edit the surface (any level).


I think now you're mixing up mipmaps and surfaces. A texture is made up of a number of surfaces, each of which is a single mipmap of the base texture. You practically always edit or render to surface 0, the base mipmap of the texture.

Quote:So is DirectX really recreating the mipmaps at each frame?


If the texture was created with D3DUSAGE_AUTOGENMIPMAP, then yes, it is. If that flag isn't used, and mipmapping is turned on, weird things will happen (the texture will look correct at close ranges, and will degrade into nothingness as you move away). So either you don't use AUTOGENMIPMAP and turn off mipmapping (faster but unmipmapped and looks grainy at distances), or you use AUTOGENMIPMAP and turn on mipmapping (looks better but slower).
_______________________________________________________________________Hoo-rah.
Quote:
I think now you're mixing up mipmaps and surfaces. A texture is made up of a number of surfaces, each of which is a single mipmap of the base texture. You practically always edit or render to surface 0, the base mipmap of the texture.

Lets say I create a texture with one surface and let DirectX generates the mipmaps. Each mipmap now becomes a surface (right?). So if I edit surface level 3, it would be like editing the third mipmap?

Or

Mipmaps are not editable. If I create a texture with 3 surfaces, then the level represent the surface not the mipmap in a surface?

Quote:
If the texture was created with D3DUSAGE_AUTOGENMIPMAP, then yes, it is. If that flag isn't used, and mipmapping is turned on, weird things will happen (the texture will look correct at close ranges, and will degrade into nothingness as you move away). So either you don't use AUTOGENMIPMAP and turn off mipmapping (faster but unmipmapped and looks grainy at distances), or you use AUTOGENMIPMAP and turn on mipmapping (looks better but slower).

I looked back at the code and in the Usage parameter the author passes 0, which means none. Now, how do I check if mipmapping is turned on or off? [Rem. this is Managed DirectX]

Darkneon
Quote:Original post by Darkneon
Quote:
I think now you're mixing up mipmaps and surfaces. A texture is made up of a number of surfaces, each of which is a single mipmap of the base texture. You practically always edit or render to surface 0, the base mipmap of the texture.

Lets say I create a texture with one surface and let DirectX generates the mipmaps. Each mipmap now becomes a surface (right?). So if I edit surface level 3, it would be like editing the third mipmap?

You don't specify how many surfaces a texture has when you create it, you specify how many mipmap levels it has -- each of which is stored in one separate surface. Thus, if you create a "texture with one surface", there is no surface level 3 to edit; there is only level 0. I think what you mean is this: if you create a texture with a full range (from its maximum resolution down to 1x1) of mipmap levels and then edit the surface that corresponds to the 3rd level mipmap, what happens? The answer is that the image shown on the third level mipmap will change, meaning that when the texture is displayed in a position where DirectX Graphics decides that the 3rd level mipmap will give the best quality/performance deal, you will see whatever you edited that level to show. In any position that results in the use of one of the other mipmap levels, you will see whatever was there before you edited anything. If the texture was created with D3DUSAGE_AUTOGENMIPMAP, you are only allowed to edit the highest resolution level, level 0. When you alter level 0 on a texture with D3DUSAGE_AUTOGENMIPMAP, DirectX scales it down repeatedly to update the other mipmap levels automatically after you commit your changes to level 0.

Quote:
Quote:
If the texture was created with D3DUSAGE_AUTOGENMIPMAP, then yes, it is. If that flag isn't used, and mipmapping is turned on, weird things will happen (the texture will look correct at close ranges, and will degrade into nothingness as you move away). So either you don't use AUTOGENMIPMAP and turn off mipmapping (faster but unmipmapped and looks grainy at distances), or you use AUTOGENMIPMAP and turn on mipmapping (looks better but slower).

I looked back at the code and in the Usage parameter the author passes 0, which means none. Now, how do I check if mipmapping is turned on or off? [Rem. this is Managed DirectX]

If you use a method of texture creation which includes a "number of levels" parameter of some sort, it controls what sort of mipmaping the texture will have. Passing 0 will cause DirectX Graphics to automatically use a full range of mipmap levels, however many it takes to go from the texture's full size down to 1x1. If you pass 1, you will get a texture that effectively doesn't use mipmaping; it will only have the top level. If you pass any other number, DirectX Graphics will try to make that many mipmap levels, starting from the texture's full size and working its way down.
Hi Mumpo, that was some very clear explanations.

Now, based on what you said and on what the author is doing, the end result is not matching. Let me explain.

Here's the code he's using to create the texture.
meshTextures = new Texture(device, 256, 256, 1, 0, Format.X8R8G8B8 ,Pool.Managed);


What do we have here? He's creating a 256x256 level 0 surface (4th parameter) and mipmapping is disabled(5th parameter).

Now, here's how he fills the surface.
        private unsafe void FillTextureUnsafe(Texture t, bool random)        {            SurfaceDescription s = t.GetLevelDescription(0);            Random r = new Random();            uint* pData = (uint*)t.LockRectangle(0,                 LockFlags.None).InternalData.ToPointer();            for (int i = 0; i < s.Width; i++)            {                for (int j = 0; j < s.Height; j++)                {                    if (random)                    {                        *pData = (uint)Color.FromArgb(                            r.Next(byte.MaxValue),                             r.Next(byte.MaxValue),                             r.Next(byte.MaxValue)).ToArgb();                    }                    else                    {                        *pData = texColor++;                        if (texColor >= 0x00ffffff)                            texColor = 0;                    }                    pData++;                }            }            t.UnlockRectangle(0);        }


So, what kind of beauty do we have here? Well, he is locking the texture and accesses surface level 0, and later on he overwrites it. Since we know that the texture has only a level 0 surface and no mipmaps, what he is doing is perfectly fine. I just want to add that this function is called every frame.

Initially, the camera was fixed. But me, feeling like playing Indiana Jones, decided to move the mesh away from it, hoping the program would crash or produce some weird results. To my surprise, none of those happened. The texture is rendered the same no matter the size of the mesh.

See for yourself. [Executable & Mesh]

My only guess is that something is happening in the background of DirectX.

"Red Alert! Red Alert! The fool is trying to render a mesh with no mipmap associated with it. We can't let the program crash. Fast! Fast! Create a mipmap from the original surface. Phieeew! Hehe, sucker, that will leave him puzzled for a while."

But that's only my guess...

A 0 mipcount means "full-chain". It saves you from having your code know in advance which textures are 512x512 so you can pass in 9, or which are 1024x1024 so you pass in 10, etc. You just say 0, and it says, "ah, you want them all".

A 1 mipcount means just the main surface, with no mipmaps. This is how you disable mips for a given texture.

D3D doesn't require mipmaps to operate. If they're present they will be used. They can be a performance win, fetching fewer cache lines of data because far away objects use the smaller surfaces. They generally are a quality win since texture filtering is based on mixing just a couple adjacent pixels. A 1024 texture with no mipmaps, scaled down onto a 20 pixel high object breaks the way hardware filters textures. You'll see all sorts of ugly shimmering going on as the object and/or your camera move.

Generally you want mips, except for fixed-sized objects like fonts, icons, and objects on your HUD. The only reason to discard mipmaps on these types of textures is because you're wasting memory.

This topic is closed to new replies.

Advertisement