Can't set texture for HLSL-sampler

Started by
8 comments, last by Juliean 13 years ago
Hi,

how do I set a texture for a sampler in my pixel shader?

texture BumpMap;
sampler2D BumpMapSampler = sampler_state
{
Texture = <BumpMap>;
};


I tried SetValue but it didn't work. What exact value (LPDIRECT3DTEXTURE9, ...) do I have to set for BumpMap, and how do I fill it in?
Advertisement
You want to call SetTexture on your ID3DXEffect, and use the "BumpMap" as the name.
You want to call SetTexture on your ID3DXEffect, and use the "BumpMap" as the name. [/quote]

I'm just using pure HLSL-shaders, no D3DXEffects.. should I better use them?
The HLSL "texture" and "sampler_state" stuff are only for effects, they don't work with plain shaders. For regular shaders, you simply declare a sampler2D and then use that in your shader code. Then in your C++ code, you call IDirect3DDevice9::SetTexture to bind a texture to a particular sampler. The binding is done with a sampler index, and you can either query this sampler index for a given shader and sampler through ID3DXConstantTable or you can explicitly specify the index in your HLSL code:

sampler2D BumpMap : register(s0) // Call SetTexture(0, texture) to bind a texture to this sampler


The effects framework serves as a wrapper around this stuff, which makes your life a bit easier. It also does the same for sampler states and regular shader constants. Either way, it's nice to have at least a basic knowledge of what goes on at a lower level so you might want to continue getting a basic shader or two working without effects before you switch over to using them.
Thx for explanation, now it is working. As I'm already using .x-files for meshes I will use effect files too as soon as I'm able to work with shaders acceptable.

But for now I've got another problem. I'm trying to get a shader for bump mapping to work, but the shader won't be created (error on CreatePixelShader as it already fails at D3DXCompileShaderFromFile).

Here is my vertex and pixel shader (pixel shader currently refuses working, haven't seen whether vertex shader is right:

// Pixel shader input structure
struct PS_INPUT
{
float2 Texture : TEXCOORD0;
float3 Light : TEXCOORD1;
float3 view : TEXCOORD2;
};


// Pixel shader output structure
struct PS_OUTPUT
{
float4 Color : COLOR0;
};


sampler2D Tex0;
sampler2D BumpMap : register(s1);


PS_OUTPUT ps_main( in PS_INPUT In )
{
PS_OUTPUT Out;

float4 color = tex2D(Tex0, In.Texture);
float3 bumpNormal = 2 * (tex2D(BumpMap, In.Texture) - 0.5);

float3 LightDir = normalize(In.Light);
float3 ViewDir = normalize(In.View);

float4 diff = saturate(dot(bumpNormal, LightDir)); // diffuse comp.

float4 shadow = saturate(4 * diff);

float4 Reflect = normalize(2 * diff * bumpNormal - LightDir);

float4 spec = min(pow(saturate(dot(Reflect, ViewDir)), 3), color.w);

Out.Color = 0.2 * color + shadow * (color * diff + spec);

return Out;
}


Can anybody see from looking over it whats wrong? Not-compiling shaders happens to me often right now, most of the time there is a simple mistake like a missing symbol or something. But this time I already checked the code 10 times and I still can't figure out whats wrong. I tried to comment out certain lines and try standard set values insteaad but that didn't bring me far eigther. Can somebody pls help me? Maybe there is some conversion error, but I don't really think so as I pretty much copied that shader from a tutorial on gamasutra..
D3DXCompileShaderFromFile gives you a string containing the compiler errors in the ppErrorMsgs parameter. Just call GetBufferPointer on the ID3DXBuffer and cast to const char*, and you'll have a string that you can output in a message box or to a log.
Aah thats great I didn't knew about that, thank you! Damn tutorials didn't tell me I can access error code that way. well maybe its also my fault because I don't spend much efford on error checking.. anyway this will make things a lot easier (I almost wondered if there was a way to see the result of shader compiling effords)!

So what I first got was i slight typing error in the input structure (view instead of View). Also there were some warnings about types beeing float3 instead of float4. So all that changed there still resists one error:

// Pixel shader input structure
struct PS_INPUT
{
float2 Texture : TEXCOORD0;
float3 Light : TEXCOORD1;
float3 View : TEXCOORD2;
};


// Pixel shader output structure
struct PS_OUTPUT
{
float4 Color : COLOR0;
};


sampler2D Tex0;
sampler2D BumpMap : register(s1);


PS_OUTPUT ps_main( in PS_INPUT In )
{
PS_OUTPUT Out;

float4 color = tex2D(Tex0, In.Texture);
float4 bumpNormal = 2 * (tex2D(BumpMap, In.Texture) - 0.5);

float3 LightDir = normalize(In.Light);
float3 ViewDir = normalize(In.View);

WARNING float3 diff = saturate(dot(bumpNormal, LightDir));
float4 shadow = saturate(4 * diff);

ERROR float4 Reflect = normalize(2 * diff * bumpNormal - LightDir);

float4 spec = min(pow(saturate(dot(Reflect, ViewDir)), 3), color.w);

Out.Color = 0.2 * color + shadow * (color * diff + spec);

return Out;
}


So first of all there is a warning X3206 in line 31 for "dot - implicit truncation of vector type". What does that exactly mean? from what I figured out it means that a vector is used with/for another type that it actually is - like filling a float4 with a float true. But how do I solve it? Is it necceassary to solve it anyway? Obviously I can't change anything in the dot() function, and everything else seems right. (EDIT: actually fixed it while typing this. just had to set LightDir and View to float4).

Still, Line 34 is giving me an error: for (symbol?) 8 it states "X3017 : cannot implicity convert from "const float3" to "float4". Yeah, its clear what that means. But it isn't clear at all why there all the sudden is a const float3 returned by the normalize()-function? Or does it mean one of the variables passed to normalize() a const float3? I don't get it. Can you/somebody pls explain to me?

EDIT:

Actually figured it out playing around a bit with the values. Had set some values accidentially to float4 instead of float3 in vein to solve the bugs at first. I almost gave up on shaders, good thing I now can see whats wrong. Well that shader is working now, but somehow I get weird results (see attachments).

Well obviously the bumpmap is working and giving some nice results, but the lighting is much to bright and the colors too dark. The dark colors are due to the *0.2-value the original colors get multiplied with (for the screens I already set the value to 0.5) and it isn't that bad after all because the colors where much too bright anyway so far. But why is the lighting so damn bright? Is this upposed to look like that? In the second picture look at the "flag" at the right edge of the picture - it's almost completly white! Are the calculations wrong or why do I get such bright results? I can multiply certain values in the shader with like 0.5 and its way better, but is this a way to go or should I rethink (or re-read, any resources maybe?) my calculations?
Your first warning means that you're assigning a larger vector to a smaller one, or using a larger vector in an operation involving smaller vector types. In your case it's the latter, since you're doing a dot product with a float4 and a float3 which means the compiler has to truncate your float4 to a float3 before it can do the dot product. Note that it's actually valid to do this...the warning is just there because it's usually not intentional. In general I find it's better to explicitly truncate using a swizzle, like this:


float4 vec4 = float4(1, 1, 1, 1);
float3 vec3 = float3(2, 2, 2);
float dotProduct = dot(vec4.xyz, vec3);


I think that's what you want to do in your case, because a normal map typically won't have anything useful in the alpha channel and you'll only want the xyz components (although doing float4(LightDir, 0.0f) will give you the same results).

As for your error, it's the opposite problem: you're trying to assign a float3 result into a float4. This isn't valid, because it's ambiguous as what you want to happen to the w component of the float4. If you only want to assign a value to the xyz components, you can use a swizzle to do this. Or you can convert the result to a float4.
Keep at it, King, you're making some good progress!
@MJP:
Thanks, I'll keep tha in mind later on. I already managed to solve the problem anyway but I will use swizzles in the future.

[quote="PropheticEdge]Keep at it, King, you're making some good progress![/quote]

Thanks! I'm actually totally eager to learn more about somewhat advanced 3d programming techniques and improve my knowledge.

Due to this I tried, right after the normal mapping, to tried to add support for parallax mapping (as it looked even more impressive and in theory shouldn't be harder to include). Well, at least I got the shader running, but it doesn't do anything.. the parallax-effect simply isn't applied. Everything looks the same as without it. There eventually is some scrolling of the texture if I rotate an object, but thats all. I've tried 3 different ways to do it and all of them failed. The first one was from the mircsoft directx-sdk-examples. It used some multipass, but didn't do much. Then I tried out an solution I found in an older thread on gamedev.net, which used multiple passes too but without a loop like the sdk. Still no reaction.

My currenct solution is from here. Thats the pixelshader now with normalmapping and parallax:

// Pixel shader input structure
struct PS_INPUT
{
float2 Texture : TEXCOORD0;
float3 Light : TEXCOORD1;
float3 View : TEXCOORD2;
//float2 Parallax : TEXCOORD3;
float3 Normal : TEXCOORD3;
};


// Pixel shader output structure
struct PS_OUTPUT
{
float4 Color : COLOR0;
};


sampler2D Tex0;
sampler2D BumpMap : register(s1);


PS_OUTPUT ps_main( in PS_INPUT In )
{
PS_OUTPUT Out;
float2 scaleBias = (0.1, -0.02);
float3 v = normalize(In.View);
float height = tex2D(BumpMap, In.Texture).a;

height = height * scaleBias.x + scaleBias.y;
float2 newTexture = In.Texture + (height * v.xy);

float4 bumpNormal = 2 * (tex2D(BumpMap, newTexture) - 0.5);

float4 color = tex2D(Tex0, newTexture);

float3 LightDir = normalize(In.Light);
float3 ViewDir = normalize(In.View);

float3 diff = saturate(dot(bumpNormal, LightDir));
float3 shadow = saturate(4 * diff);

float3 Reflect = normalize(2 * diff * bumpNormal - LightDir);

float3 spec = min(pow(saturate(dot(Reflect, ViewDir)), 3), color.w)*0.5;

float4 Color;
Color.xyz = (0.5 * color + shadow * (color * diff + spec));
Color.w = 1.0;

Out.Color = Color;

return Out;
}


Although I use the new texture coordinates, I get no effect. I quessed it could have something to do with wrong tangents, but after all the normal mapping is working so this isn't very likely. Anyway, here my vertex shader:

struct VS_INPUT
{
float4 Position : POSITION;
float3 Normal : NORMAL;
float2 Texture : TEXCOORD0;
float3 Tangent : TANGENT0;
};

struct VS_OUTPUT
{
float4 Position :POSITION;
float2 Texture : TEXCOORD0;
float3 Light : TEXCOORD1;
float3 View : TEXCOORD2;
//float2 Parallax :TEXCOORD3;
float3 Normal : TEXCOORD3;
};

float4x4 WorldViewProj;
float4x4 World;
float3 Eye;
float3 LightDir;

VS_OUTPUT vs_main( in VS_INPUT In )
{
VS_OUTPUT Out = (VS_OUTPUT)0;
Out.Position = mul(In.Position, WorldViewProj); // transform Position

float3x3 worldToTangentSpace;
worldToTangentSpace[0] = mul(In.Tangent, World);
worldToTangentSpace[1] = mul(cross(In.Tangent, In.Normal), World);
worldToTangentSpace[2] = mul(In.Normal, World);

Out.Texture = In.Texture.xy;

Out.Light.xyz = mul(worldToTangentSpace, LightDir); // L
float4 PosWorld = mul(In.Position, World);
float3 Viewer = Eye - PosWorld; // V
Out.View = mul(worldToTangentSpace, Viewer);

Out.Normal = normalize(In.Normal);

return Out;
}


[s]Does anyone notice whats wrong with these shaders? I don't see anything, because after trying 3 different algorythms which all just caused the graphics to stay the same (not even any glitches at all; except for my custom generated terrain which lacks normals and tangets - a good argument why wrong tangents shouldn't be the problem) and the fact the lighting, which pretty much uses the same tangents and view, I don't know anything to solve that anymore.. maybe someone else?

EDIT: Oh yeah heightmap is alright too because I'm using the original graphics from the microsoft sdk parallax example, which I compiled and tested..

[/s]EDIT2: Nevermind, I eventually figured out that I was just using a different vertex shader the whole time, so tangent space was actually not right set oO. So now I get an effect, but not the one I actually wanted to have. Look at the attachment. Its more like some sort of distrobe-effect, while the textures themself move around on the mesh while moving it.

So, does anyone know whats going on here? Once again I tested all 3 algorythms I found and they all produced the same results. Do I calculate the tangents right? On mesh creation I call D3DXComputeNormals(lpMesh, NULL);
D3DXComputeTangent(lpMesh, 0, 0, 0, 0, NULL);

Is this fine? If yes, are there maybe any calculation mistakes? I really can't figure it out..Normal mapping btw. is with the right vertex shader now working without any problems and is looking absolutly awesome!

This topic is closed to new replies.

Advertisement