This project is read-only.

Problem with shader

Oct 6, 2009 at 6:41 PM

 

Hi!

I can't  compile this shader (error: Expected ';' in shader header ...\Graphics\Effects\AdvWater.fx ):

 //CompilerOptions = ParentNamespace, InternalClass


float Time = 0;

float4x4 matWorldViewProj : WORLDVIEWPROJECTION;
float4x4 matWorld : WORLD;
float4x4 matWorldView : WORLDVIEW;
float4x4 matViewI : VIEWINVERSE;

float fBumpHeight = 0.5f;

float2 vTextureScale = float2( 4.0f, 4.0f );

float2 vBumpSpeed = float2( -0.0f, 0.05f );

float fFresnelBias = 0.025f;

float fFresnelPower = 1.0f;

float fHDRMultiplier = 1.0f;

float4 vDeepColor = float4( 0.0f, 0.40f, 0.50f, 1.0f );

float4 vShallowColor = float4( 0.55f, 0.75f, 0.75f, 1.0f );

float4 vReflectionColor = float4( 1.0f, 1.0f, 1.0f, 1.0f );

float fReflectionAmount = 0.5f;

float fWaterAmount = 0.5f;

float fWaveAmp = 0.5f;

float fWaveFreq = 0.1f;

texture tNormalMap;

texture tEnvMap;

sampler2D s0 = sampler_state {
Texture = (tNormalMap);

MipFilter = Linear;
MinFilter = Linear;
MagFilter = Linear;
};

samplerCUBE s1 = sampler_state {
Texture = (tEnvMap);

MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};

//--------------------------------------------------
// Vertex shader
//--------------------------------------------------
struct VSOUTPUT {
float4 vPos : POSITION;
float2 vTex : TEXCOORD0;
float3 vTanToCube[3] : TEXCOORD1;
float2 vBump0 : TEXCOORD4;
float2 vBump1 : TEXCOORD5;
float2 vBump2 : TEXCOORD6;
float3 vView : TEXCOORD7;
};

// Wave
struct Wave {
float fFreq; // Frequency (2PI / Wavelength)
float fAmp; // Amplitude
float fPhase; // Phase (Speed * 2PI / Wavelength)
float2 vDir; // Direction
};

#define NUMWAVES 3
Wave Waves[NUMWAVES] = {
{ 1.0f, 1.00f, 0.50f, float2( -1.0f, 0.0f ) },
{ 2.0f, 0.50f, 1.30f, float2( -0.7f, 0.7f ) },
{ .50f, .50f, 0.250f, float2( 0.2f, 0.1f ) },
};

// Wave functions
float EvaluateWave( Wave w, float2 vPos, float fTime ) {
return w.fAmp * sin( dot( w.vDir, vPos ) * w.fFreq + fTime * w.fPhase );
}

float EvaluateWaveDifferential( Wave w, float2 vPos, float fTime ) {
return w.fAmp * w.fFreq * cos( dot( w.vDir, vPos ) * w.fFreq + fTime * w.fPhase );
}

float EvaluateWaveSharp( Wave w, float2 vPos, float fTime, float fK )
{
return w.fAmp * pow( sin( dot( w.vDir, vPos ) * w.fFreq + fTime * w.fPhase )* 0.5 + 0.5 , fK );
}

float EvaluateWaveSharpDifferential( Wave w, float2 vPos, float fTime, float fK )
{
return fK * w.fFreq * w.fAmp * pow( sin( dot( w.vDir, vPos ) * w.fFreq + fTime * w.fPhase )* 0.5 + 0.5 , fK - 1 ) * cos( dot( w.vDir, vPos ) * w.fFreq + fTime * w.fPhase );
}

VSOUTPUT VS_Water( float4 inPos : POSITION, float3 inNor : NORMAL, float2 inTex : TEXCOORD0,
float3 inTan : TANGENT, float3 inBin : BINORMAL ) {
VSOUTPUT OUT = (VSOUTPUT)0;

// Generate some waves!
Waves[0].fFreq = fWaveFreq;
Waves[0].fAmp = fWaveAmp;

Waves[1].fFreq = fWaveFreq * 2.0f;
Waves[1].fAmp = fWaveAmp * 0.5f;

Waves[2].fFreq = fWaveFreq * 3.0f;
Waves[2].fAmp = fWaveAmp * 1.0f;

// Sum up the waves
inPos.y = 0.0f;
float ddx = 0.0f, ddy = 0.0f;

for( int i = 0; i < NUMWAVES; i++ ) {
inPos.y += EvaluateWave( Waves[i], inPos.xz, Time );
float diff = EvaluateWaveDifferential( Waves[i], inPos.xz, Time);
ddx += diff * Waves[i].vDir.x;
ddy += diff * Waves[i].vDir.y;
}

// Output the position
OUT.vPos = mul( inPos, matWorldViewProj );

// Generate the normal map texture coordinates
OUT.vTex = inTex * vTextureScale;

Time = fmod( Time, 100.0 );
OUT.vBump0 = inTex * vTextureScale + Time * vBumpSpeed;
OUT.vBump1 = inTex * vTextureScale * 2.0f + Time * vBumpSpeed * 4.0;
OUT.vBump2 = inTex * vTextureScale * 4.0f + Time * vBumpSpeed * 8.0;

// Compute tangent basis
float3 vB = float3( 1, ddx, 0 );
float3 vT = float3( 0, ddy, 1 );
float3 vN = float3( -ddx, 1, -ddy );

// Compute the tangent space to object space matrix
float3x3 matTangent = float3x3( fBumpHeight * normalize( vT ),
fBumpHeight * normalize( vB ),
normalize( vN ) );

OUT.vTanToCube[0] = mul( matTangent, matWorld[0].xyz );
OUT.vTanToCube[1] = mul( matTangent, matWorld[1].xyz );
OUT.vTanToCube[2] = mul( matTangent, matWorld[2].xyz );

// Compute the world space vector
float4 vWorldPos = mul( inPos, matWorld );
OUT.vView = matViewI[3].xyz - vWorldPos;

return OUT;
}

//--------------------------------------------------
// Pixel shader
//--------------------------------------------------
//float3 Refract( float3 vI, float3 vN, float fRefIndex, out bool fail )
//{
//float fIdotN = dot( vI, vN );
//float k = 1 - fRefIndex * fRefIndex * ( 1 - fIdotN * fIdotN );
//fail = k < 0;
//return fRefIndex * vI - ( fRefIndex * fIdotN + sqrt(k) )* vN;
//}

float4 PS_Water( VSOUTPUT IN ) : COLOR0 {

// Fetch the normal maps (with signed scaling)
float4 t0 = tex2D( s0, IN.vBump0 ) * 2.0f - 1.0f;
float4 t1 = tex2D( s0, IN.vBump1 ) * 2.0f - 1.0f;
float4 t2 = tex2D( s0, IN.vBump2 ) * 2.0f - 1.0f;

float3 vN = t0.xyz + t1.xyz + t2.xyz;


// Compute the tangent to world matrix
float3x3 matTanToWorld;

matTanToWorld[0] = IN.vTanToCube[0];
matTanToWorld[1] = IN.vTanToCube[1];
matTanToWorld[2] = IN.vTanToCube[2];

float3 vWorldNormal = mul( matTanToWorld, vN );
vWorldNormal = normalize( vWorldNormal );

// Compute the reflection vector
IN.vView = normalize( IN.vView );
float3 vR = reflect( -IN.vView, vWorldNormal );

// Sample the cube map
float4 vReflect = texCUBE( s1, vR.zyx );
vReflect = texCUBE( s1, vR );

// Exaggerate the HDR effect
vReflect.rgb *= ( 1.0 + vReflect.a * fHDRMultiplier );

// Compute the Fresnel term
float fFacing = 1.0 - max( dot( IN.vView, vWorldNormal ), 0 );
float fFresnel = fFresnelBias + ( 1.0 - fFresnelBias ) * pow( fFacing, fFresnelPower);

// Compute the final water color
float4 vWaterColor = lerp( vDeepColor, vShallowColor, fFacing );

return vWaterColor * fWaterAmount + vReflect * vReflectionColor * fReflectionAmount * fFresnel;
}

//--------------------------------------------------
// Techniques
//--------------------------------------------------
technique AdvancedWater
{
pass Pass1
{
VertexShader = compile vs_2_0 VS_Water();
PixelShader = compile ps_2_0 PS_Water();
}
}

Oct 6, 2009 at 9:18 PM
Edited Oct 6, 2009 at 9:20 PM

Hi.

The problem is fairly simple, but it will require some rejigging of the shader. Unfortunately an error case isn't being reported correctly.

Because the shader is converted into .net code; properties are created for all the global constants used by the shader.
However there are certain types of constants that cannot be generated.
In this case, the Wave structure you have defined. This can't be mapped to a .net equivalent, (eg, float, matrix, etc).

There are two options here, one is easy, one not so easy. It depends if you want to be able to modify the values at runtime.
If you don't want to modify the Wave values from your C# code, then move the Waves array definition into the vertex shader body. Done! A runtime editable property won't need to be created then.

Wave is just a set of 3 floats plus a two float direction...
The other option, if you wanted to change the values at runtime from C#, would be to break it into an float3[] array and a float2[] array representing the data it stores.

There is code in there to test for cases where global structures are used in a shader, and properly report it as not supported - however in this case some other code was erroring out first.

At one point I did support generating structures for types defined in a shader, however this became *extraordinarily* difficult to maintain and keep clean - plus it was still surprisingly tricky to assign the values.  I'll also note that setting the Waves value with an Effect is very fiddly. :-)

 

Does that make sense?

Oct 7, 2009 at 3:53 AM

Thank you for the detailed answer!

I try to move Wave array to vertex shader and get another two errors in generated code in method vspre():"Using the field "W", which may not be assigned a value" .

Oct 7, 2009 at 3:59 AM
Edited Oct 7, 2009 at 4:11 AM

In other simple shader i'd have anoter warning (Discovered unreachable code) in generated code.

it generates next code in bind method:

if ((null != null))
{
state.SetShaderConstants(null, pc);
}

 

Shader:

//CompilerOptions = ParentNamespace, InternalClass
float4 color = float4(1, 1, 1, 1);
texture colorMap;

sampler colorSampler = sampler_state
{
Texture = (colorMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = LINEAR;
MinFilter = LINEAR;
MipFilter = LINEAR;
};

struct VertexShaderInput
{
float4 Position : POSITION0;
float2 Coords : TEXCOORD0;
};

struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 Coords : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;

output.Position = input.Position;
output.Coords = input.Coords;

return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float4 texColor = tex2D (colorSampler, input.Coords);
return float4(texColor.rgb * color.rgb, color.a * texColor.a );
}

technique RenderInScreanSpace
{
pass Pass0
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}