Bobby Anguelov's Blog

A day in the life of a wannabe game developer

DirectX 10 Tutorial 3 – Textures

So it’s been sometime since the last tutorial and I apologize for that, I’ve been busy wrapping up my exams for my second degree and finishing off a mini thesis for one of my subjects. So now that it’s all over with I‘ve sat down and done a small tutorial on dx10 texturing.

A lot of other tutorials leave texturing for later on in the tutorial but I’m going to do it now because it’s so simple and further illustrates the point of shader programs and what role they play.

Texturing?

So what is texturing? You can think of it like applying wallpaper to a blank wall, you take an image and attach it to an object in your scene. Well that’s not entirely true, what texturing actually does is use an image as a reference for what color an object is. Where before we set the color for each vertex and then let the API automatically interpolate the colors between vertices now we’re giving it an image to sample for those colors.

I’m not going to go into great detail regarding mipmaps and so on since it isn’t really necessary at this point, hopefully I’ll have the time to come back to it at a later stage and even if I don’t google is your friend :P

Texturing occurs in the pixel shader stage of the pipeline, just before fragments are rasterized and so the bulk of the texturing code (all 1 line of it) needs to be done in HLSL.

There is one last thing I need to cover before I can get into the code, as I said earlier we give a object an image to use as a reference for the colors on the surface defined in the object but how does the API know which pixel in the image to use for a set of world co-ordinates on the surface? Well this is actually quite simple.

image1

If we look at the above picture, for a 128×128 pixel texture which we want to use for the quad on the right. The first we need to do is set up some sort of coordinate system for the texture. We use the letters u and v for the two axes, please notice that v increases in a downwards direction, u and v are known as texture coordinates. This is because in an image, the first pixel is the top left image and the last pixel is the bottom right. Another restriction on this coordinate system is that u and v are real numbers ranging from 0 to 1 where 1 is 100% of the texture dimension. So the texture coordinates u=0.5, v=0.5 will return the center pixel in a texture.

Okay to attaching this texture to an object defined by a set of vertices in world space, we need to add a piece of information to each vertex: the texture coordinate of that vertex in respect to the texture. So for any two vertices, the API will sample the color values of the texture between the texture coordinates specified for each vertex.  At any point in the object it will have a texture coordinate, to calculate what pixel to use in the image as the color reference is simple. The pixel coordinates x,y are simply calculated as such: x= round(u*(textureWidth-1)), y= round(v*(textureHeight-1)).  Simple huh?

In the above image we want to use the entire texture for the quad and so specify the u,v coordinates accordingly. We also show the corresponding pixel coordinates for a point on the object with u,v coordinates: (0.2,0.3). Okay so that an idiots guide to texturing theory. Let’s dig into the code.

The first thing we need to do is take tutorial 2 and modify it for texturing. We remove the rotation for the triangle and add an extra vertex to generate a quad as in the below image:

image2

The code for the quad is:

v[0] = vertex( D3DXVECTOR3(-1,-1,0), D3DXVECTOR4(1,0,0,1));
v[1] = vertex( D3DXVECTOR3(-1,1,0), D3DXVECTOR4(0,1,0,1));
v[2] = vertex( D3DXVECTOR3(1,-1,0), D3DXVECTOR4(0,0,1,1));
v[3] = vertex( D3DXVECTOR3(1,1,0), D3DXVECTOR4(1,1,0,1));

Loading the Textures

So let’s load our textures, our first step is setting up storage for our textures and a way to pass it through to the shader program:

std::vector<ID3D10ShaderResourceView*> textureSRV;
ID3D10EffectShaderResourceVariable* pTextureSR;

Textures are loaded as ID3D10 resources, to which you need to create a view; a view tells DX how to access a particular resource. Since a texture is a shader resource that’s the type of view we need. The second variable is how we pass the texture id to the HLSL shaders.

So how do we load a texture from an image file? Well if you thought it would be a complicated and involved process you’re wrong, it’s a single function call (D3DX10CreateShaderResourceViewFromFile), and the code to load multiple textures into our texture storage is below.

vector<string> filenames;
filenames.push_back("textures/t1.bmp");
filenames.push_back("textures/t2.bmp");
filenames.push_back("textures/t3.bmp");

//load textures
for ( int i=0; i < (int) filenames.size(); i++ )
{
	textureSRV.push_back(NULL);

	if ( FAILED( D3DX10CreateShaderResourceViewFromFile( pD3DDevice, filenames[i].c_str(), NULL, NULL, &textureSRV[i], NULL ) ) )
	{
		  char err[255];
		  sprintf_s(err, "Could not load texture: %s!", filenames[i].c_str());
		  return fatalError( err );
	}
}

That function merges two steps, the creation of the texture and the resulting view to it, in one. Okay so now we’ve loaded the texture now what? Well we need to modify our vertex struct to support texture coordinates, texture coordinates have two dimensions, u and v, horizontal and vertical respectively. To attach a texture to a polygon you need to specify what part of the texture you want to put over the polygon.

struct vertex
{
	D3DXVECTOR3 pos;
	D3DXVECTOR4 color;
	D3DXVECTOR2 texCoord;
}

We use a 2d vector to specify the u,v coordinates for each vertex. So this also means the code for the qaud has changed to:

v[0] = vertex( D3DXVECTOR3(-1,-1,0),D3DXVECTOR4(1,0,0,1),D3DXVECTOR2(0.0f, 1.0f) );
v[1] = vertex( D3DXVECTOR3(-1,1,0),D3DXVECTOR4(0,1,0,1),D3DXVECTOR2(0.0f, 0.0f) );
v[2] = vertex( D3DXVECTOR3(1,-1,0),D3DXVECTOR4(0,0,1,1),D3DXVECTOR2(1.0f, 1.0f) );
v[3] = vertex( D3DXVECTOR3(1,1,0),D3DXVECTOR4(1,1,0,1),D3DXVECTOR2(1.0f, 0.0f) );

Since we changed the vertex struct we also need to modify the inputlayout accordingly, remember that the input layout tells DX what each vertex looks like. All we need to change is the input_element_desc for the input layout:

D3D10_INPUT_ELEMENT_DESC layout[] =
{
	{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
	{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
	{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D10_INPUT_PER_VERTEX_DATA, 0 }
};

Last step is to tell the API which texture to which just before we draw an object. Since in most basic cases we will only be using a single texture (multi-texturing comes later)  we only need a single texture shader resource variable which we just update to the texture we want.

//set texture
pTextureSR->SetResource( textureSRV[textureIndex] );

Okay so now if we run the program we get… The exact same thing as before. Why?! Well this is obvious since we havent touched the pixel shader program at all.

Texturing using the Pixel Shader

So lets just tweak the shader program (basicEffect.fx), first thing we need to do is specify a texture variable for the shader as such:

Texture2D tex2D;

Then we create a samplerState, remember when I said earlier that we sample the texture to get a color at a specific set of u,v coordinates, a texture resource resource in HLSL has a sample method that samples that texture and returns the value at a specific point, now the way in which it sample that texture is done via the sampleState object. This object sets all the parameters for the default sampler. A very basic samplerState is show below:

SamplerState linearSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

It has three elements: a filter which specifies how the sampling is to be done over the texture, in our case we’re just doing a basic linear sampling (all the sampling states and their descriptions are available in the SDK docs, the addressU and addressV specify how to handle u and v values that lie outside the 0 to 1 range.

Remember how I said that u and v are in the range 0 to 1, well that’s not exactly true, sometimes to want to texture an object using 4 smaller versions of a texture rather than stretching the texture to fit the the object. The below image shows what happens for a few common addressU , addressV values:

image31

There are other state variables for the samplerState object, once again all the info necessary is in the sdk docs.

Now we need to modify the vs_input and ps_input structs to handle the extra 2d texcoord variable:

struct VS_INPUT
{
	float4 Pos : POSITION;
	float4 Color : COLOR;
	float2 Tex : TEXCOORD;
};

struct PS_INPUT
{
	float4 Pos : SV_POSITION;
	float4 Color : COLOR;
	float2 Tex : TEXCOORD;
};

And the vector and pixel shaders accordingly. The only difference in the pixel shader is that for texturing we need to return the sampled color and not the vertex color. We use the sample method on the texture object , the sampler state we defined earlier and the texture coordinates we specified earlier.

PS_INPUT VS( VS_INPUT input )
{
	PS_INPUT output;
	output.Pos = mul( input.Pos, World );
	output.Pos = mul( output.Pos, View );
	output.Pos = mul( output.Pos, Projection );
	output.Color = input.Color;
	output.Tex = input.Tex;

	return output;
}

float4 textured( PS_INPUT input ) : SV_Target
{
	return tex2D.Sample( linearSampler, input.Tex );
}

float4 noTexture( PS_INPUT input ) : SV_Target
{
	return input.Color;
}

We also create two new techniques “full” and “texturing disabled”:

technique10 full
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, textured() ) );
    }
}

technique10 texturingDisabled
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, noTexture() ) );
    }
}

Then we load these two techniques exactly as we did in the previous tutorial. If we compile and run the program we’re presented with a now textured quad.

image4

If we change the texture co-ordinates to :

v[0] = vertex( D3DXVECTOR3(-1,-1,0), D3DXVECTOR4(1,0,0,1), D3DXVECTOR2(0.0f, 2.0f) );
v[1] = vertex( D3DXVECTOR3(-1,1,0), D3DXVECTOR4(0,1,0,1), D3DXVECTOR2(0.0f, 0.0f) );
v[2] = vertex( D3DXVECTOR3(1,-1,0), D3DXVECTOR4(0,0,1,1), D3DXVECTOR2(2.0f, 2.0f) );
v[3] = vertex( D3DXVECTOR3(1,1,0), D3DXVECTOR4(1,1,0,1), D3DXVECTOR2(2.0f, 0.0f) );

The result is this:

image5

You can download the source code for this tutorial below. In the code you’ll notice that I add a method to swap the texture on the quad by modifying the textureIndex when I set the texture and to disable texturing by using the “texturingDisabled” technique instead of “Full”. Take a look at the wndProc method to see the controls and how they work.

I hope you’ve enjoyed this tutorial, I’ve already started working on the 4th one which will be about meshes and index buffers. I’m going to slowly write the turorials and build upon each one towards the final goal of rendering a field of thousands of blades of waving grass. I feel its pretty pointless to show you all the section seperately without explaining how they all link up together.

Source Code

Download the visual studio 2008 project: dxTutorial3.zip

29 November 2008 Posted by Bobby | DirectX 10, DirectX 10 Tutorials, Game Development, General, Graphics Programming, HLSL, Programming | , , , , , , , , | 6 Comments

Fallout 3: Falling flat…

So i’ve had plenty of time to play with fallout3 before being hit with a game stopping bug and now i’m stuck waiting for a patch. The fallout series, rather let me say the original fallout games are still my favorite games of all time and i was one of those rapid fanboys that couldn’t wait for number 3. So what do I think of fallout 3? I’ll sum it up in the most common sentence you’ll find online: “oblivion with guns”, i’m severely underwhelmed and dissapointed wuith this game and it only goes to show that bethesda haven’t seem to have learnt anything from their oblivion experience or maybe they just dont care.

So this isnt gonna be like every other review post online (not to mention is my personal opinion) where I go into how the games starts out with your birth, that entire section of the game is unneccessary and pointless. It has absolutely no relevance on the game and only serves to annoy the hell out of you, especially if you want to restart the game. The first two had it right, give you a brief intro and throw you into the action. Last thing that kinda annoyed me about that whole section was as you leave the vault, you get a prompt asking if you want to change something? you just spent 30 minutes, being led by the hand to create your character and now you get the option to change everything?! what the hell was the point of that whole exercise then, couldn’t they just have given you that screen to start with?

Super Duper Mart
Super Duper Mart

Lets ignore the shockingly weak storyline, the first two games had the character go out into the world on epic quests (which i’ll admit weren’t the strongest plotlines either but that wasnt where the beauty of the game was), here they send you on a search after daddy dearest. Next let me bitch about the world, while the world at first, is quite impressive (again that oblivion moment after leaving the prison – de ja voo any one?), that feeling doesnt last for long. The entire game consists of predefined routes (dont even try explore cause you cant) through the city and dungeons, oh wait i mean subway tunnels. Seriously? you went and put the annoying and pointless dungeon crawling element of oblivion into fallout? WHY THE HELL?!?! Now just to add to this annoyance they decided that most areas aren’t accessible unless you go through the tunnel first. Hmm, i have to go over that mound of rubble, can i climb over it, oh no, i need to now mission through another generic subway tunnel to get there. This is how i’ve spent the bulk of the game. I’m gonna come back to the world a bit later.

Lets move onto the character system, after you set up your initial SPECIAL stats, there is a perk at every level where you can get an extra SPECIAL point to any stat, so thoses initial choices dont really matter cause you can just add points when you feel like it. Then the skill system has also been nerfed, tagging skills makes no difference, it just add an extra 15pts when you start to that skill. Where in the first games tagged skills got increased with 3 points for every point spent while un-tagged skills only increased with 1. So here I am at level 16: lockpick at 85, repair at 100, small guns at 100, science at 80, speech at 90, medicine at 40, barter at 40, large guns at 40. My character stats are ridiculous as well: str 6, per 6, endurance 6, charisma 7, intelligence 8, agility 9, luck 6. So my character can do practically do everything in the game, i can lockpick, hack and repair everything i come across! The whole point (for me) of the original fallouts was to replay the game with a unique character that could only do certain things in the game, this gave me a vastly different  game experience each time.

I remember playing fallout 2 with a dumb gunfighter and then i played with a smart science geek and ended up having a totally different experiences, i was able to do quests in different ways with different outcomes. Where I may have gunned my way through an objective the first time, i talked my way out of it the second. Actually bothering to invest in the speech skill mattered, in oblivion 3, sorry i mean fallout 3 it doesnt matter since there are no restrictions on anything. If you want, use the speech skill but it doesnt open up any hidden game areas, major quests changes etc, you can get more money, YAY (sarcasm), not that there is anything worth buying, but before i get to the items, combat and inventory system, i need to spend more time discussing the world.

In the original fallouts the world was a large area on the west coast of the US, in FO3 we’re limited to a single cityscape. From a gameplay perspective it makes sense since you cant really create a seemless world that covers such a large area but then again the old system in the previous games allowed the designers to create unique and interesting areas in the game, not cut and paste kilometres of generic ruins and tunnels. While seemless worlds have their advatages, It felt that there was most thougth and care involved in the world design of the originals. There were settlements which upon entering made you feel like this is a group of people struggling to survive, there was politics, personal and power struggles. The world felt gritty and real. In contrast Fallout 3 feels plastic and empty, there are no really memorable characters or locations, like for example at first glance when you see the capitol building you’re like “WOW!” then you walk inside and it ends up being a five room, linear dungeon crawl. What a fucking let down. The majority of the world is like this, made up of generic ruin that you cant explore and just serve as scenery.

I still remember being a prize fighter in new reno, helping out the super mutant sheriff in broken hills, finding timmy in the well, being forced into a shotgun wedding, taking out the bandit lair, i remember taking about a magic the gathering ripoff with a ghoul and getting hand to hand lessons in san francisco, there are tons of moments like those from the originals that i still remember to this day. I played fallout 3 last week and cant remember a single character from megaton apart from the sheriff that died in like 5 minutes. The first fallouts had entire settlements that made you feel like you had actually stumbled upon a surviving city, what do we have in fallout 3? megaton and rivet city, both are around the size of the smallest settlement in fallout1/2. You run into a few more settlements in FO3 but the settlement consists of a few semi-identical rooms and perhaps at best 3 unique characters. 

Oh Noez, a Raid3r iz Killings Me!
Oh Noez, a Raid3r iz Killings Me!

The dialogues are boring, the quests when you can find them are lame as hell, collect nuka cola and deliver it to a character? you’re kidding right? this isnt WOW, i dont want to search the world for bottles of nuka cola just to get 100caps as a reqard seeing as i’m carrying 5000 and have nothing to spend them on. What the hell? why would i even want to do that? I’m sorry bethesda but stop trying to make RPGs, just stick to action oriented hack and slash games. In your dialogue and quests, there is the good path and then there is the bad path. You’d have to be a moron not to be able to distinguish between the two. There never really is any gray areas, I cant remember ever having to make any serious choice that really affected something in the world. Blow up megaton or dont blow up megaton, hmmm, tough choice… Thats why i loved the originals you often ended up being good by doing bad things, or hell half the time there really wasnt a good choices period. You were never a shining knight or some moustache twisting villain, you were a human trying to survive.

I mentioned that the quests were pretty lame, let me give a few examples. I guess i should give a spoiler warning but it really doesnt matter, i’m not giving anything away. Apart from the nuka cola collection quest i mentioned, there are various characters in the game that need certion types of items and will pay you to deliver them, if money was a problem i might consider doing it but since i’m flowing in the cash from just missioning about there is no need. I also found it pretty ironic when the outcast brotherhood of steel wouldnt buy power armor from me, even though he specifically said he was looking for exactly that. Then lets get to some of the more “complex” quests which mainly consist of choosing who to kill or fetching an item from a “dungeon” oh wait i mean ruin. And the quests outcomes have no real effect on anything. In rivet city you get a choice to frame someone or blackmail the quest giver, if doesnt matter what you do, there are no downsides to either of the two option nor any benefits to doing the quest. Thats the major problem i have with the game, there is no incentive for me to do anything. Cash, items and ammo are everywhere, i dont need to do quests for money cause even with the moeny there is nothing to buy. Also i’m around half way through the game and power armor is dropping left right and center?! It kinda ruins any sort of excitement in getting hold of it. I understand that they need all the items for repair purposes but personally i would have made repairing items possible buy using the junk you find in the world, that way you could limit the items and provide more of a sense of achievement in getting a high end item. That way they could have made repairing something extremely hard and so finding a item in excellent shape would also be an exciting moment.

Okay enough of that, lets move on to the atrocious inventory system, yes i know the game is meant to be played on consoles too but your original fanbase for fallout are pc gamers, so you decided to reward them with shitty one button interface? ugh! then they decided to implement a weight limit for your inventory only to make ammo weightless, so i’m running around with 50 missiles, like 5000 bullets of various calibres, 6 mini nukes, couple of thousand energy cells but if I try carry three sets of armor, i cant move? What prompted that design choice, did you think console players wouldnt be able to micromanage their inventory? “OH noez, i actually have to plan how much ammo i take with me, this game is too hard, my brain is gonna go boom. Time for some Gears of War or Halo where i dont have to think as hard”.

I was also dissapointed with the lack of variety and the total abundance of items. While there may not have been that many in the previous fallouts, i was so excited when i finally got hold of an assault rifle quite a while into the game. I had to work for it and barely killed the guy holding it, I felt a sense of achievement. Here within 30mins of wandering in the wasteland you have practically every weapon available in the game, the only thing you end up needing to buy is stimpacks and maybe some ammo now and then. Where is the sense of achievement, the sense that you had to work for something. GAH! The condition and repair system is something that i do like and i think its an a good addition, but it isnt enough to save an otherwise bleak item list.

The combat system funnily enough is somethign that doesnt bother me, i actually kinda like it, it might not be the original turn based system but it works. VATS was quite a good idea and i cant fault them on it. The difficulty of the game tho i can fault. I’ve died 3 times in the game and two of the times it was cause i ran out of ammo in the beginning of the game but once i tapped into the never ending supply of ammo lying around that didnt happen again. I have yet to found an enemy that was challenging, i’ve massacred entire villages without needing to use a single stimpack. Super mutants are easy enough to kill even at low levels. Correct me if i’m wrong but werent super mutants a bitch to kill in the first two. Mutants (which dont seem to exists in FO3) were hard enough and if you saw a super mutant you were always like “Oh shit”. In FO3 its more of an “oh great another 4 mutants” moment.

Then there is the obligatory barbie’s playhouse moment, wherein you are presented with a house in megaton if you do the good karma quests, which you can kit out a bit, with absolutely no purpose. You can get a workbench, a laboratory, a nuka cola machine and several themes. Why? this isnt the sims? I couldnt care less what my house looks like. Then there is the custom items that you can build at workbenches but there isnt much point since they arent really all that great, You can just as well stick to the standard items.  

Fallout 3 is simply oblivion with a skin, the shitty empty villages are there, the pointless dungeon crawls and fetch quests are there. Its a silly hack and slash with practically no character customization, everything that made the original fallouts what they were is gone. This is a glorified fallout tactics, a dumbed down, watered down attempt at the greatness of the first games. It is a failure as an RPG, but as an action hack and slash it isnt so bad, but thats not fallout, fallout wasnt a hack and slash. Fallout3 compared to the orignals is like what icewind dale was to baldurs gate. If I was bethesda I’d realize that my strengths lie in the action RPG realm and not even bother with trying to make this great “in-depth” and detailed world. They just cant. Even now as a dungeon crawl it fails, since there is no epic item to find, no epic boss to kill, no amazing abilities to unlock. Bethesda doesnt seem to understand what made the original fallouts great.

24 November 2008 Posted by Bobby | Game Reviews, Gaming, General | | 34 Comments