# Multi Texturing for Shaders using X files

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

## Recommended Posts

hi everyone. can any one please help me with my problem? i'm writing a bumpmapper using HLSL and i want to simulate bump mapping (along with phong shading effects). however, when it comes to loading multiple texture there is a strange behaviour in my program. im loading the mesh from an .x file (which only has one uv channel but its ok since i will use the same uv for both diffuse and bump maps). then i change the structure to: ------------------------------------------------------------------- D3DVERTEXELEMENT9 g_VertexDeclaration[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, { 0, 28, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, { 0, 36, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, { 0, 44, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 2 }, { 0, 56, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 3 }, D3DDECL_END() }; hr = Mesh->CloneMesh(D3DXMESH_MANAGED, g_VertexDeclaration, device, &clonedMesh); ---------------------------------------------------------------------- and i compute the tangent and the normal using dx functionality. i also set two textures and associate samplers with them (one for diffuse and one for bump map). but here is where the problem arises: when in the render function i pass the textures (device->settexture/sampler sets) everything seems fine. but in truth, only the latter texture that i pass works and the other one is completely blank. let me explain a bit more clear! in the render function i pass: ---------------------------------------------------------------------- device->SetTexture( shadeTexDesc.RegisterIndex, shadeTex); device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); device->SetTexture( bumpTexDesc.RegisterIndex, bumpTex); device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); ----------------------------------------------------------------------- where shadeTexDesc is assigned to a tex sampler and bumpTexDesc is assigned to another sampler.(sampler SamplerTexture; sampler SamplerBump;) and bumpTex and shadeTex represent the actual textures loaded from files. but in the pixel shader, i cant get a hold on to the SamplerTexture. it returns (0,0,0,0) after tex2D(SamplerTexture, texturecoord). and if i change the place of it with the bumpTexDesc in the render function, only this one will work and the bump texture is blank. hope i could explain the question. i dont know where or what im doing wrong, but i cant load both the textures at the same time. my guess goes to the device->setFVF and device->setstreamsource. but so long that i dont have them (using .x files :( ) i dont know how to fix them. but i could as well be wrong. i would really appretiate it if some one could help me. im really stuck. thanks in advance.

##### Share on other sites
When you cloned your mesh, did you fill in the second set of texture coordinates? You have to make sure that you filled those in yourself because the Clone method doesn't know how to initialize those values.

In fact, you don't even need to have a second set of texture coordinates. In your pixel shader, you could use the same set of texture coordinates to access both textures without a problem.

You also mentioned something about using SetFVF. When you use shaders, you have to use SetVertexDeclaration. SetFVF is for when you want to use the fixed function pipeline. Also, make sure that you're not accidentally setting both textuers to be at the same sampler in your source code.

neneboricua

##### Share on other sites
thank you very much for trying to help.
as you said (and i said in my post as well) i dont really need to set the second uv because i use the original one to map both diffuse and bump maps. (one set of uv is enough for both mappings in my case)
in regards to SetFVF and SetVertexDecleration, by my understanding, i dont need to set anything since the xfile takes care of it (though i could be wrong).
so it narrows it down to one thing: setting different sampler states...

//decleration:	IDirect3DTexture9* shadeTex;	IDirect3DTexture9* bumpTex;		D3DXHANDLE shadeTexHandle;	D3DXHANDLE bumpTexHandle;		D3DXCONSTANT_DESC shadeTexDesc;	D3DXCONSTANT_DESC bumpTexDesc;//Init(device)://loading the texture from file: (XTexturename, XBumpTextureName are defined earlier in the code)HRESULT result = D3DXCreateTextureFromFile(device, XTexutename,  &shadeTex);if FAILED(result)     ::MessageBox(NULL, "couldnt load the texture!", "Texture failed", NULL);result = D3DXCreateTextureFromFile(device, XBumpTextureName, &bumpTex);if FAILED(result)    ::MessageBox(NULL, "couldnt load the bump map texture!", "Texture failed", NULL);//Setting the handles:shadeTexHandle= BumpMapperConstTablePS->GetConstantByName(0, "SamplerTexture");bumpTexHandle = BumpMapperConstTablePS->GetConstantByName(0, "SamplerBump");//added to verify the texture description. in order to use PS correctly.BumpMapperConstTablePS->GetConstantDesc(shadeTexHandle, &shadeTexDesc, &count);BumpMapperConstTablePS->GetConstantDesc(bumpTexHandle, &bumpTexDesc, &count);//Render Fucntion (device, dt):device->SetTexture(     shadeTexDesc.RegisterIndex, shadeTex);device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);device->SetTexture(    bumpTexDesc.RegisterIndex, bumpTex);device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

as you can probably guess, the samplers in the pixel shader are:

sampler SamplerTexture;sampler SamplerBump;

...
now when i test this:

--------------------- PARTIAL CODE, NOT COMPLETE: -----------------
//input.tex = TEXCOORD0vector kd = tex2D(SamplerTexture, input.tex);float4 output = kd;return output;

instead of seeing the diffuse texture, i see the bump texture! eventhough i used the diffuse sampler and not the bump sampler to create it!!!

i dont really want to make the post too long, but here i add my render function. maybe it makes things more clear:

// CODE: RENDER FUNCTION. the attributes which are used are all properly set before in the initialization!// Renderbool CBumpMapper::Render(IDirect3DDevice9* device, float timeDelta){	static float y = 0.0f;	D3DXMATRIX yRot;	D3DXMatrixRotationY(&yRot, y);	y += timeDelta;	if( y >= 6.28f )		y = 0.0f;	worldMatrix = yRot;	device->SetTransform(D3DTS_WORLD, &worldMatrix);	device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,  DEFAULT_BACKGROUND_COLOR, 1.0f, 0);	device->BeginScene();        device->SetVertexShader(BumpMapperVS);	device->SetPixelShader(BumpMapperPS);	D3DXMATRIX worldView;	D3DXMATRIX worldViewProj;	D3DXMATRIX worldViewIT;	worldView     = worldMatrix * viewMatrix;	worldViewProj = worldMatrix * viewMatrix * projMatrix;	D3DXMATRIX inverse;	D3DXMatrixInverse(&inverse, 0, &worldView);	D3DXMatrixTranspose(&worldViewIT, &inverse);	BumpMapperConstTableVS->SetMatrix(		device, 		worldViewHandleVS,		&worldView);	BumpMapperConstTableVS->SetMatrix(		device,		worldViewProjHandleVS,		&worldViewProj);		BumpMapperConstTableVS->SetMatrix(		device,		worldViewITHandleVS,		&worldViewIT);	D3DXVECTOR4 kd = D3DXVECTOR4(1,0,0,1);	BumpMapperConstTablePS->SetVector(		device,		kdHandlePS,		&kd);	D3DXVECTOR4 ks = D3DXVECTOR4(5,5,5,1);	BumpMapperConstTablePS->SetVector(		device,		ksHandlePS,		&ks);			for(int i = 0; i < Mtrls.size(); i++)		{			device->SetTexture(     shadeTexDesc.RegisterIndex, shadeTex);			device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);			device->SetTexture(    bumpTexDesc.RegisterIndex, bumpTex);			device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);			clonedMesh->DrawSubset(i);		}			device->EndScene();		device->Present(0, 0, 0, 0);	return true;}

Edited by Coder - Used source and code tags. Check GDNet Forums FAQ for formatting guidelines

[Edited by - Coder on March 15, 2005 1:54:30 PM]

##### Share on other sites
Your code looks reasonable for the most part. By the way, since you're using shaders, there's no need to call device->SetTransform(D3DTS_WORLD, &worldMatrix); because this call is part of the fixed function pipeline. Your vertex shader is taking care of transforming your model into the appropriate space.

As far as not needed to call either SetFVF or SetVertexDeclaration when using DrawSubset, you're probably right. But I think that DrawSubset might be internally calling SetFVF. If so, it may be causing some problems. You should really try to call DrawIndexedPrimitive yourself. That way, you are in total control of what calls are getting made to D3D. The ID3DXMesh interface is great for optimizing meshes so that they render in the most efficient manner, but the actual rendering part of the interface isn't the best because it has to be totally generic. Calling DIP yourself isn't all that hard either. It will also be much more efficient than DrawSubset because DrawSubset has to call SetIndexBuffer and SetVertexBuffer every single time. But since you know how many materials you need to render, you can call SetIndexBuffer/SetVertexBuffer just once before you enter your materials loop. Once you switch to using DrawIndexedPrimitive, you'll need to call SetVertexDeclaration before rendering anything.

Also, I could be wrong, but I'm not sure that the RegisterIndex member of the D3DXCONSTANT_DESC is really the sampler being used. It could be but I haven't found this documented anywhere. As a test, use the "register" keyword in your shader to force a variable in your pixel shader to use a specific sampler. For example, if you wanted to set your diffuse texture to sampler 0 and your bump texture to sampler 1, you would do this in your pixel shader

sampler2D SampleTexture:register(s0); // Use sampler 0
sampler2D SampleBump:register(s1); // Use sampler 1

Now in your source code, you can set the textures in the same samplers. This isn't as generic as what you're trying to do but at least it will help you in narrowing down the problem.

neneboricua

##### Share on other sites
thank you very much man. you are a real expert in this :)
for those of you who might be interested, the solution was this:
i changed the code from

			device->SetTexture(     shadeTexDesc.RegisterIndex, shadeTex);			device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(shadeTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);			device->SetTexture(    bumpTexDesc.RegisterIndex, bumpTex);			device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);			device->SetSamplerState(bumpTexDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

to

		device->SetTexture(     0, shadeTex);		device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);		device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);		device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);		device->SetTexture(     1, bumpTex);		device->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);		device->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);		device->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

(used fixed sampler states 0 and 1 and addressed them in ps directly)
and in the pixel shader, i changed the sampler decleration from:

sampler2D SamplerBump; sampler2D SamplerTexture;

to

sampler2D SamplerBump:register(s1);sampler2D SamplerTexture:register(s0);

and now everything works fine. (accomplished using 2 different textures, using the same uv for both channels in ps while loading an .x file (cloned version)).

again thank you very much man. you helped me a great deal.

1. 1
Rutin
47
2. 2
3. 3
4. 4
5. 5

• 13
• 10
• 12
• 10
• 13
• ### Forum Statistics

• Total Topics
632992
• Total Posts
3009755
• ### Who's Online (See full list)

There are no registered users currently online

×