Sign in to follow this  
Ginger

Help with shader

Recommended Posts

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]

Share this post


Link to post
Share on other sites
Oops! I think I put too much things in my post, sorry.
My question was :
Why is my shader code giving me the correct output at EffectEdit but when I tried to use it from my application, the output was just a single tone yellow surface with the wooden stripes missing? What is wrong with my code that causes this to happen? Thanks.

Ginger

Share this post


Link to post
Share on other sites
It is the host application's responsibility to generate the textures used for the wood pattern. Your app should interpret the annotations associated with the texture objects after the effect is loaded, and do just that - just like the EffectEdit app does.

Share this post


Link to post
Share on other sites
Which is exactly why I avoid making my FX files in IDE programs like EffectEdit and RenderMonkey and FX Composer! Make your own (very simple and basic) program that you can load your effects in to. That way you know exactly how what your making is going to interface with what you want. Most of the IDEs have extra junk that is built into it (like rendertargets for instance) that most people don't realize have to be implemented by the core program once you want to start using it.

Good luck.

Share this post


Link to post
Share on other sites
"It is the host application's responsibility to generate the textures used for the wood pattern. Your app should interpret the annotations associated with the texture objects after the effect is loaded, and do just that - just like the EffectEdit app does."

Hi, I think you might be right and I am missing something that I don't know.. The wooden part is generated by my pixel shader. But how can my application interpret the texture object after the shader is loaded? I haven't seen any code that teaches me do that. Can u give me some tips as to how can I do that?

I will write my own IDE after this project is completed. Thanks!
Ginger.

Share this post


Link to post
Share on other sites
Hello Nik02, I tried to do what u said about letting the application know about the texture.. It seems to change something for the better! Now I can at least see the textures on my object... but now I have a new problem.. the textures that appeared are of very big pixel size.. Looks like I got another headache coming up! Thanks for you help!!

Ginger.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this