I’m trying to implement per-pixel displacement mapping, but when trying to render geometry with the shader I get an InvalidOperationException (Shader Compilation Failed).
Here is my HLSL shader:
float4x4 World;
float4x4 View;
float4x4 Projection;
float3 LightPos;
float3 EyePos;
float bumpDepth;
const float3 NormalizationFactor = float3(1, 1, 1);
const int NUM_ITERATIONS = 8;
texture ModelTexture;
sampler2D colorSampler = sampler_state {
Texture = (ModelTexture);
MinFilter = Linear;
MagFilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};
texture NormalMap;
sampler2D normalSampler = sampler_state {
Texture = (NormalMap);
MinFilter = Linear;
MagFilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};
texture DistanceTexture;
sampler3D distanceSampler = sampler_state {
Texture = (DistanceTexture);
MinFilter = Linear;
MagFilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float3 Tangent : TANGENT0;
float3 Binormal : BINORMAL0;
float2 TexCoord : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float3 TanEyeVec : NORMAL0;
float3 TanLightVec : NORMAL1;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = mul(World * View * Projection, input.Position);
output.TexCoord = input.TexCoord;
float3 eyeVec = EyePos - input.Position;
float3 tanEyeVec;
tanEyeVec.x = dot(input.Tangent, eyeVec);
tanEyeVec.y = dot(input.Binormal, eyeVec);
tanEyeVec.z = -bumpDepth * dot(input.Normal, eyeVec);
output.TanEyeVec = tanEyeVec;
float3 lightVec = LightPos - input.Position;
float3 tanLightVec;
tanLightVec.x = dot(input.Tangent, lightVec);
tanLightVec.y = dot(input.Binormal, lightVec);
tanLightVec.z = dot(input.Normal, lightVec);
output.TanLightVec = tanLightVec;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float3 offset = normalize(input.TanEyeVec);
offset *= NormalizationFactor;
float3 texCoord = float3(input.TexCoord, 1);
for (int i = 0; i < NUM_ITERATIONS; i++)
{
float distance = tex3D(distanceSampler, texCoord);
texCoord += distance * offset;
}
// Compute derivatives of unperturbed texcoords.
// This is because the offset texcoords will have discontinuities
// which lead to incorrect filtering.
float2 dx = ddx(input.TexCoord.xy);
float2 dy = ddy(input.TexCoord.xy);
// Do bump-mapped lighting in tangent space.
// 'normalTex' stores tangent-space normals remapped
// into the range [0, 1].
float3 tanNormal = 2 * tex2D(normalSampler, texCoord.xy , dx, dy) - 1;
float3 tanLightVec = normalize(input.TanLightVec);
float diffuse = dot(tanNormal, tanLightVec);
// Multiply diffuse lighting by texture color
float4 color = diffuse * tex2D(colorSampler, texCoord.xy, dx, dy);
color.a = 1;
return saturate(color);
}
technique BumpMapped
{
pass Pass1
{
VertexShader = compile vs_3_0 VertexShaderFunction();
PixelShader = compile ps_3_0 PixelShaderFunction();
}
}
And here is the generated GLSL shaders:
Pixel Shader:
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#if GL_ARB_shader_texture_lod
#extension GL_ARB_shader_texture_lod : enable
#define texture2DGrad texture2DGradARB
#define texture2DProjGrad texture2DProjARB
#elif GL_EXT_gpu_shader4
#extension GL_EXT_gpu_shader4 : enable
#else
#define texture2DGrad(a,b,c,d) texture2D(a,b)
#define texture2DProjGrad(a,b,c,d) texture2DProj(a,b)
#endif
uniform vec4 ps_uniforms_vec4[1];
uniform vec4 ps_uniforms_ivec4[1];
const vec4 ps_c1 = vec4(1.0, 2.0, -1.0, 0.0);
vec4 ps_r0;
vec4 ps_r1;
vec4 ps_r2;
vec4 ps_r3;
#define ps_c0 ps_uniforms_vec4[0]
#define ps_i0 ps_uniforms_ivec4[0]
uniform sampler2D ps_s0;
uniform sampler2D ps_s1;
uniform sampler3D ps_s2;
varying vec4 vTexCoord0;
#define ps_v0 vTexCoord0
#define ps_oC0 gl_FragColor
void main()
{
ps_r0.xyz = normalize(ps_v1.xyz);
ps_r0.xyz = ps_r0.xyz * ps_c0.xyz;
ps_r1.xy = ps_v0.xy;
ps_r1.z = ps_c1.x;
for (int rep1 = 0; rep1 < ps_i0.x; rep1++) {
ps_r2 = texture3D(ps_s2, ps_r1.xyz);
ps_r1.xyz = (ps_r2.xxx * ps_r0.xyz) + ps_r1.xyz;
}
ps_r0.xy = dFdx(ps_v0.xy);
ps_r0.zw = dFdy(ps_v0.xy);
ps_r2 = texture2DGrad(ps_s1, ps_r1.xy, ps_r0.xy, ps_r0.zw);
ps_r2.xyz = (ps_r2.xyz * ps_c1.yyy) + ps_c1.zzz;
ps_r3.xyz = normalize(ps_v2.xyz);
ps_r1.z = dot(ps_r2.xyz, ps_r3.xyz);
ps_r0 = texture2DGrad(ps_s0, ps_r1.xy, ps_r0.xy, ps_r0.zw);
ps_oC0.xyz = clamp(ps_r0.xyz * ps_r1.zzz, vec3(0.0), vec3(1.0));
ps_oC0.w = ps_c1.x;
}
Vertex Shader:
#ifdef GL_ES
precision highp float;
precision mediump int;
#endif
uniform vec4 vs_uniforms_vec4[15];
uniform vec4 posFixup;
vec4 vs_r0;
vec4 vs_r1;
vec4 vs_r2;
vec4 vs_r3;
vec4 vs_r4;
vec4 vs_r5;
#define vs_c0 vs_uniforms_vec4[0]
#define vs_c1 vs_uniforms_vec4[1]
#define vs_c2 vs_uniforms_vec4[2]
#define vs_c3 vs_uniforms_vec4[3]
#define vs_c4 vs_uniforms_vec4[4]
#define vs_c5 vs_uniforms_vec4[5]
#define vs_c6 vs_uniforms_vec4[6]
#define vs_c7 vs_uniforms_vec4[7]
#define vs_c8 vs_uniforms_vec4[8]
#define vs_c9 vs_uniforms_vec4[9]
#define vs_c10 vs_uniforms_vec4[10]
#define vs_c11 vs_uniforms_vec4[11]
#define vs_c12 vs_uniforms_vec4[12]
#define vs_c13 vs_uniforms_vec4[13]
#define vs_c14 vs_uniforms_vec4[14]
attribute vec4 vs_v0;
#define vs_o0 gl_Position
attribute vec4 vs_v1;
varying vec4 vTexCoord0;
#define vs_o1 vTexCoord0
attribute vec4 vs_v2;
vec4 vs_o2;
attribute vec4 vs_v3;
vec4 vs_o3;
attribute vec4 vs_v4;
void main()
{
vs_r0 = vs_c0;
vs_r0 = vs_r0 * vs_c4;
vs_r1.xyz = vs_r0.yxz * vs_c8.yxz;
vs_r0.x = vs_r0.w * vs_c8.w;
vs_r2.x = vs_r1.y;
vs_r3 = vs_c1;
vs_r3 = vs_r3 * vs_c5;
vs_r4.xyz = vs_r3.xzy * vs_c9.xzy;
vs_r0.y = vs_r3.w * vs_c9.w;
vs_r2.y = vs_r4.x;
vs_r3 = vs_c2;
vs_r3 = vs_r3 * vs_c6;
vs_r3.xyz = vs_r3.xyz * vs_c10.xyz;
vs_r0.z = vs_r3.w * vs_c10.w;
vs_r2.z = vs_r3.x;
vs_r5 = vs_c3;
vs_r5 = vs_r5 * vs_c7;
vs_r5.xyz = vs_r5.xyz * vs_c11.xyz;
vs_r0.w = vs_r5.w * vs_c11.w;
vs_o0.w = dot(vs_r0, vs_v0);
vs_r2.w = vs_r5.x;
vs_o0.x = dot(vs_r2, vs_v0);
vs_r4.x = vs_r1.z;
vs_r1.y = vs_r4.z;
vs_r1.z = vs_r3.y;
vs_r4.z = vs_r3.z;
vs_r1.w = vs_r5.y;
vs_r4.w = vs_r5.z;
vs_o0.z = dot(vs_r4, vs_v0);
vs_o0.y = dot(vs_r1, vs_v0);
vs_r0.xyz = vs_c13.xyz + -vs_v0.xyz;
vs_o2.x = dot(vs_v2.xyz, vs_r0.xyz);
vs_o2.y = dot(vs_v3.xyz, vs_r0.xyz);
vs_r0.x = dot(vs_v1.xyz, vs_r0.xyz);
vs_o2.z = vs_r0.x * -vs_c14.x;
vs_r0.xyz = vs_c12.xyz + -vs_v0.xyz;
vs_o3.x = dot(vs_v2.xyz, vs_r0.xyz);
vs_o3.y = dot(vs_v3.xyz, vs_r0.xyz);
vs_o3.z = dot(vs_v1.xyz, vs_r0.xyz);
vs_o1.xy = vs_v4.xy;
gl_Position.y = gl_Position.y * posFixup.y;
gl_Position.xy += posFixup.zw * gl_Position.ww;
gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;
}
Any tips?
Also, as a side note, what is the current plan for Geometry shaders?