Hi experts out there! This is my effect file (extracted from DXSDK sample):
// transformations
float4x3 WorldView ;//: WORLDVIEW;
float4x4 Projection ;//: PROJECTION;
// light direction (view space)
float3 lightDir < string UIDirectional = "Light Direction"; > = {1.0, -1.0, 1.0};
//{0.577, -0.577, 0.577};
// light intensity
float4 I_a = { 0.3f, 0.3f, 0.3f, 1.0f }; // ambient
float4 I_d = { 1.0f, 1.0f, 1.0f, 1.0f }; // diffuse
float4 I_s = { 0.6f, 0.6f, 0.6f, 1.0f }; // specular
// material reflectivity
float4 k_a = { 0.2f, 0.2f, 0.2f, 1.0f }; // ambient
float4 k_d = { 1.0f, 0.7f, 0.2f, 1.0f }; // diffuse
float4 k_s = { 1.0f, 1.0f, 1.0f, 1.0f }; // specular
float n = 64.0f; // power
#define DARK 0.3f
#define LIGHT 1.0f
// model dependent wood parameters
#define RINGSCALE 10.0f
#define POINTSCALE 2.0f
#define TURBULENCE 1.0f
#define VOLUME_SIZE 32
// textures
float4 Linear(float2 Pos : POSITION) : COLOR0
{
return float4(Pos, Pos);
}
// function used to fill the volume noise texture
float4 GenerateNoise(float3 Pos : POSITION) : COLOR0
{
float4 Noise = (float4)0;
for (int i = 1; i < 256; i += i)
{
Noise.r += abs(noise(Pos * 500 * i)) / i;
Noise.g += abs(noise((Pos + 1)* 500 * i)) / i;
Noise.b += abs(noise((Pos + 2) * 500 * i)) / i;
Noise.a += abs(noise((Pos + 3) * 500 * i)) / i;
}
return Noise;
}
texture LinearTex < string function = "Linear"; int width = 16; int height = 16; >;
texture NoiseTex < string type = "VOLUME"; string function = "GenerateNoise"; int width = VOLUME_SIZE, height = VOLUME_SIZE, depth = VOLUME_SIZE; >;
struct VS_OUTPUT
{
float4 Pos : POSITION;
float3 Diff : COLOR0;
float3 Spec : COLOR1;
float3 Tex0 : TEXCOORD0;
float3 Tex1 : TEXCOORD1;
float2 Tex2 : TEXCOORD2;
};
VS_OUTPUT VS(
float3 Pos : POSITION,
float3 Norm : NORMAL)
{
VS_OUTPUT Out = (VS_OUTPUT)0;
float3 L = -lightDir;
float3 P = mul(float4(Pos, 1), (float4x3)WorldView); // position (view space)
float3 N = normalize(mul(Norm, (float3x3)WorldView)); // normal (view space)
float3 R = normalize(2 * dot(N, L) * N - L); // reflection vector (view space)
float3 V = -normalize(P); // view direction (view space)
Out.Pos = mul(float4(P, 1), Projection); // position (projected)
Out.Diff = I_a * k_a + I_d * k_d * max(0, dot(N, L)); // diffuse + ambient
Out.Spec = I_s * k_s * pow(max(0, dot(R, V)), n/4); // specular
Out.Tex1 = 0.5 * Pos * POINTSCALE;
Out.Tex0 = Out.Tex1 * TURBULENCE;
Out.Tex2 = RINGSCALE * length(Out.Tex1.xz);
return Out;
}
// samplers
sampler NoiseSamp = sampler_state
{
texture = <NoiseTex>;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
MIPFILTER = LINEAR;
MINFILTER = LINEAR;
MAGFILTER = LINEAR;
};
sampler LinearSamp = sampler_state
{
texture = <LinearTex>;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
MIPFILTER = LINEAR;
MINFILTER = LINEAR;
MAGFILTER = LINEAR;
};
// PS11 version is a gross approximation
float4 PS11(VS_OUTPUT In) : COLOR0
{
float4 Color;
float r;
// note the use of a linear texture with wrapped texcoords to emulate 'frac'
r = tex2D(LinearSamp, In.Tex2) + 0.1 * (tex3D(NoiseSamp, In.Tex1) - 0.5);
Color.rgb = In.Diff * lerp(DARK, LIGHT, saturate(0.8 - 0.6 * r))
+ In.Spec;
Color.w = 1;
return Color;
}
technique TWood_PS_1_1
{
pass P0
{
VertexShader = compile vs_1_1 VS();
PixelShader = compile ps_1_1 PS11();
}
}
I've tested this effect on EffectEdit and it works perfectly well, giving me nice wooden texture. However, when I set and use my shader using the 2 functions below, the output of the effect was not what I expected. Instead of my wooden texture, I got a single tone yellowish texture with no stripes.
void SetWoodShader()
{
// Check hardware support version 3_0
D3DCAPS9 Caps;
g_pD3DDevice->GetDeviceCaps(&Caps);
if(Caps.VertexShaderVersion < D3DVS_VERSION(1,1))
{
g_pD3DDevice->SetSoftwareVertexProcessing(1);
}
if(Caps.PixelShaderVersion < D3DPS_VERSION(1,1))
{
MessageBox(NULL, "PS can't support!", "test", MB_OK);
return;
}
DWORD flags;
flags = D3DXSHADER_NO_PRESHADER| D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT | D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
hr = D3DXCreateEffectFromFile( g_pD3DDevice, "wood.fx", NULL, NULL, flags , NULL, &g_pEffect, &pErrorMsgs );
if ( FAILED( hr ) && pErrorMsgs != 0 && pErrorMsgs->GetBufferPointer() != 0 )
{
MessageBox(NULL, (char *)pErrorMsgs->GetBufferPointer(), "test", MB_OK); // output shader error (for debugging)
return;
}
// Set the global parameters for the shader
D3DXMATRIXA16 matWorldView = rotation * matView;
g_pEffect->SetMatrix("WorldView", &matWorldView);
g_pEffect->SetMatrix("Projection", &matProj);
}
void UseWoodShader()
{
D3DXHANDLE hTechnique = g_pEffect->GetTechniqueByName("TWood_PS_1_1");
hr = g_pEffect->SetTechnique(hTechnique);
if(FAILED(hr))
{
MessageBox(NULL, "Create Technique Failed", "test", MB_OK);
return;
}
UINT nPasses;
hr = g_pEffect->Begin(&nPasses, 0);
if(FAILED(hr))
{
MessageBox(NULL, "Begin Effect Failed", "test", MB_OK);
return;
}
for(UINT Pass = 0; Pass < nPasses; Pass++)
{
if(FAILED(hr = g_pEffect->BeginPass(Pass)))
{
MessageBox(NULL, "Cannot begin pass", "Error", MB_OK);
return;
}
// draw here!
Draw(5,10,10,1,-1,3,4,6);
g_pEffect->EndPass();
}
g_pEffect->End();
}
- I am using REF since I do not have a graphic card and REF works fine with the shader at EffectEdit.
- This is my declaration written before DrawPrimitive() is called, done within the pass:
D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
D3DDECL_END()
};
if( FAILED( hr = g_pD3DDevice->CreateVertexDeclaration( decl, &m_pVertexDeclaration ) ) )
{
MessageBox(NULL, "Create Vertex Declaration failed!", "Create failed", MB_OK);
return;
}
- Within my Draw() function, I simply:
=>CreateVertexBuffer()
=>Fill in my vertex buffer using Lock and Unlock
=>SetVertexDeclaration to decl[] shown previously
=>SetStreamSource() where
struct VERTEX
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
};
was used to compute size of vertex
=>DrawPrimitive().
Edited by Coder: Source tags are a good idea [smile]
[Edited by - Coder on December 5, 2004 11:34:47 AM]