History: Monster-source
Source of version: 2 (current)
Copy to clipboard
{CODE(caption="Monster.source",wrap="1",colors="c++")} //TWEAK HERE
//
// #define PER_VERTEX 1 -> TODO /?/
// #define SPOT_LIGHTS 1 -> TODO
// #define DETAIL_BUMP_TEXTURE 1 -> TODO (bump means normal map, height in alpha optional)
// #define DETAIL_DIFFUSE_TEXTURE 1 -> TODO
// #define SPECULAR_POWER_TEXTURE 1 -> TODO (stored in diffuse texture's alpha)
// #define ENVIRONMENT_MAPPING 1 -> TODO
// #define AMBIENT_OCCLUSION 1 -> TODO (modulates envir. lighting aka. ambient)
// #define OPACITY_TEXTURE 1 -> TODO (offset-mapped decals, for.ex)
//
// Other suggestions?
#define FADING 0
//fading is buggy, experimental guarantees :)
#define ATTENUATION 0
#define LIGHT0_IS_DIRECTIONAL 0
//if u have directional light (suppose a healthy 1 only), it is always light0
//(regarding that you turn off lights in RECOMMENDED ORDER of 2,1,0)
//so do not attenuate it, but then we have power to attenuate light1, and light2
//even with offset mapping on !
#define ANY_TEXTURE 1
#define DIFFUSE_TEXTURE 1
#define AT_LEAST_PERPIXEL 1
#define AT_LEAST_NORMAL_MAPPING 1
#define OFFSET_MAPPING 1
#define AMBIENT 1
#define DIFFUSE 1
#define SPECULAR 1
#define LIGHT0 1
#define LIGHT1 1
#define LIGHT2 1
/////////////////////////////////////////////////////////////////////////////////////////////////
// VERT COMES
/////////////////////////////////////////////////////////////////////////////////////////////////
//quite chaotic form, maybe more logical arrangement possible
void monster_vs
(
float4 position : POSITION,
float3 normal : NORMAL,
out float4 oPosition : POSITION,
#if ANY_TEXTURE
float2 uv : TEXCOORD0,
out float2 oUv : TEXCOORD0,
uniform float scale,
#endif
#if AT_LEAST_NORMAL_MAPPING
float3 tangent : TEXCOORD1,
#elif AT_LEAST_PERPIXEL //just normal perpixel, use texcoord7 to transmit to frag (holds eyedir in offset case)
out float3 oNorm : TEXCOORD7,
#endif
// Still in frag shader!
// #if AMBIENT
// uniform float4 ambient,
// out float4 oColor : COLOR,
// #endif
#if LIGHT0
uniform float4 lightPosition0, // object space
#if DIFFUSE
out float3 oLightDir0 : TEXCOORD1,
#endif
#if SPECULAR
out float3 oHalfAngle0 : TEXCOORD4,
#endif
#endif
#if LIGHT1
uniform float4 lightPosition1, // object space
#if DIFFUSE
out float3 oLightDir1 : TEXCOORD2,
#endif
#if SPECULAR
out float3 oHalfAngle1 : TEXCOORD5,
#endif
#endif
#if LIGHT2
uniform float4 lightPosition2, // object space
#if DIFFUSE
out float3 oLightDir2 : TEXCOORD3,
#endif
#endif
#if ATTENUATION
out float4 dist : TEXCOORD6, // .x, .y, and .z is used for light distances
#elif SPECULAR
out float3 oHalfAngle2 : TEXCOORD6,
#endif
#if OFFSET_MAPPING //needs eye no matter specular
uniform float3 eyePosition, // object space
out float3 oEyeDir : TEXCOORD7,
#elif SPECULAR //no need to output eye, even if normal-mapping is on
uniform float3 eyePosition, // object space
#elif FADING
uniform float3 eyePosition, // object space
//Fading will modify alpha, and will be passed to frag in COLOR,
//though I could do it with dist.w, which is unmodified even with atten
//but I do not use dist without atten, anyway. Dunno which is faster.
#endif
#if FADING
out float4 oFadeColor : COLOR,
uniform float4 fadefirst,
uniform float4 fadesecond,
#endif
uniform float4x4 worldviewproj
)
{
oPosition = mul(worldviewproj , position);
#if ANY_TEXTURE
oUv = uv * scale;
#endif
#if AT_LEAST_NORMAL_MAPPING
float3 binormal = cross(tangent, normal);
float3x3 rotation = float3x3(tangent, binormal, normal);
#elif AT_LEAST_PERPIXEL
oNorm = normal;
#endif
#if OFFSET_MAPPING //no matter specular, I need eye for offsetting
float3 eyeDir = eyePosition - position.xyz;
eyeDir = normalize(mul(rotation, eyeDir));
oEyeDir = eyeDir;
#elif SPECULAR //I need eye only if specular other than offset, plus no eye output now
float3 eyeDir = normalize(eyePosition - position.xyz);
#if AT_LEAST_NORMAL_MAPPING //eye needs adjustment if normal-mapping
eyeDir = normalize(mul(rotation, eyeDir));
#endif
#endif
//if DIFFUSE is commented out, we only need temp_lightDirX for oHalfAngle
//and if both DIFFUSE and SPECULAR is out, we shall not calculate any lighting
#if LIGHT0
#if ATTENUATION
#if LIGHT0_IS_DIRECTIONAL
// light0 is directional, atten is on, but we do not atten light0
float3 temp_lightDir0 = normalize(lightPosition0.xyz - (position * lightPosition0.w));
dist.x = 0;
//I need dist.x even I do not use it now. Compiler blah-blah about continous oTex6.
#else
float3 temp_lightDir0 = lightPosition0.xyz - (position * lightPosition0.w);
dist.x = length(temp_lightDir0);
temp_lightDir0 = temp_lightDir0 / dist.x; //normalize it this way
// oatten.x = 1/(atten.y + dist0*atten.z + dist0*dist0*atten.w);
// Attenuation calc, could be even much faster if it could be done in vertex shader.
// Think about leaving kl component only, and calculating atten value here,
// instead doing only distance here, and calculating atten in frag shader.
#endif
#else
float3 temp_lightDir0 = normalize(lightPosition0.xyz - (position * lightPosition0.w));
#endif
#if AT_LEAST_NORMAL_MAPPING
temp_lightDir0 = normalize(mul(rotation, temp_lightDir0));
#if DIFFUSE
oLightDir0 = temp_lightDir0;
#endif
#elif DIFFUSE //just normal perpixel
oLightDir0 = temp_lightDir0;
#endif
#if SPECULAR
oHalfAngle0 = normalize(eyeDir + temp_lightDir0);
#endif
#endif
#if LIGHT1
#if ATTENUATION
float3 temp_lightDir1 = lightPosition1.xyz - (position * lightPosition1.w);
dist.y = length(temp_lightDir1);
temp_lightDir1 = temp_lightDir1 / dist.y; //normalize it this way
#else
float3 temp_lightDir1 = normalize(lightPosition1.xyz - (position * lightPosition1.w));
#endif
#if AT_LEAST_NORMAL_MAPPING
temp_lightDir1 = normalize(mul(rotation, temp_lightDir1));
#if DIFFUSE
oLightDir1 = temp_lightDir1;
#endif
#elif DIFFUSE //just normal perpixel
oLightDir1 = temp_lightDir1;
#endif
#if SPECULAR
oHalfAngle1 = normalize(eyeDir + temp_lightDir1);
#endif
#endif
#if LIGHT2
#if ATTENUATION
float3 temp_lightDir2 = lightPosition2.xyz - (position * lightPosition2.w);
dist.z = length(temp_lightDir2);
temp_lightDir2 = temp_lightDir2 / dist.z; //normalize it this way
#else
float3 temp_lightDir2 = normalize(lightPosition2.xyz - (position * lightPosition2.w));
#if SPECULAR
oHalfAngle2 = normalize(eyeDir + temp_lightDir2);
#endif
#endif
#if AT_LEAST_NORMAL_MAPPING
temp_lightDir2 = normalize(mul(rotation, temp_lightDir2));
#if DIFFUSE
oLightDir2 = temp_lightDir2;
#endif
#elif DIFFUSE //just normal perpixel
oLightDir2 = temp_lightDir2;
#endif
#endif
#if FADING
float ratio = saturate(1-(distance(eyePosition, position.xyz)-fadefirst) / fadesecond);
oFadeColor = float4(0,0,0,ratio);
#endif
}
// Helper: Expand a range-compressed vector
float3 expand(float3 v)
{
return (v - 0.5) * 2;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// FRAG COMES
/////////////////////////////////////////////////////////////////////////////////////////////////
void monster_ps(
#if DIFFUSE_TEXTURE
uniform sampler2D diffuseMap : register(s1),
float2 uv : TEXCOORD0,
#elif ANY_TEXTURE
float2 uv : TEXCOORD0,
#endif
#if LIGHT0
#if DIFFUSE
float3 LightDir0 : TEXCOORD1,
uniform float4 lightDiffuse0,
#endif
#if SPECULAR
float3 HalfAngle0 : TEXCOORD4,
uniform float4 lightSpecular0,
#endif
#endif
#if LIGHT1
#if DIFFUSE
float3 LightDir1 : TEXCOORD2,
uniform float4 lightDiffuse1,
#endif
#if SPECULAR
float3 HalfAngle1 : TEXCOORD5,
uniform float4 lightSpecular1,
#endif
#endif
#if LIGHT2
#if DIFFUSE
float3 LightDir2 : TEXCOORD3,
uniform float4 lightDiffuse2,
#endif
#endif
#if OFFSET_MAPPING
float3 EyeDir : TEXCOORD7,
uniform float4 scaleBias,
uniform sampler2D normalHeightMap : register(s0),
#elif AT_LEAST_NORMAL_MAPPING
uniform sampler2D normalHeightMap : register(s0),
#elif AT_LEAST_PERPIXEL //no normal-mapping, use standard normal, in eyedir's place
float3 normalvec : TEXCOORD7,
#endif
#if SPECULAR
uniform float exponent0,
// uniform float exponent1,
// uniform float exponent2,
#endif
#if AMBIENT
uniform float4 ambient,
#endif
#if ATTENUATION //if on, supposed to have light0 on as well, OR light0_directional!
float4 dist : TEXCOORD6,
#if !LIGHT0_IS_DIRECTIONAL
uniform float4 atten0,
#endif
#if LIGHT1
uniform float4 atten1,
#endif
#if LIGHT2
uniform float4 atten2,
#endif
#elif SPECULAR
#if LIGHT2
float3 HalfAngle2 : TEXCOORD6,
uniform float4 lightSpecular2,
#endif
#endif
#if FADING
float4 inFadeColor : COLOR,
#endif
out float4 oColor : COLOR
)
{
#if OFFSET_MAPPING
float height = tex2D(normalHeightMap, uv).a;
float scale = scaleBias.x;
float bias = scaleBias.y;
float displacement = (height * scale) + bias;
float3 uv2 = float3(uv, 1);
float2 newTexCoord = ((EyeDir * displacement) + uv2).xy;
float3 bumpVec = expand(tex2D(normalHeightMap, newTexCoord ).xyz);
// float3 bumpVec = tex2D(normalHeightMap, newTexCoord ).xyz;
float3 N = normalize(bumpVec);
#if DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, newTexCoord).xyz;
#endif
#elif AT_LEAST_NORMAL_MAPPING
float3 bumpVec = expand(tex2D(normalHeightMap, uv).xyz);
// float3 N = tex2D(normalHeightMap, uv).xyz;
float3 N = normalize(bumpVec);
#if DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, uv).xyz;
#endif
#elif AT_LEAST_PERPIXEL
float3 N = normalize(normalvec);
#if DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, uv).xyz;
#endif
#elif DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, uv).xyz;
#endif
//If different exponents for different specular-lights, change 3 places here!
#if LIGHT0
#if DIFFUSE
float NdotL0 = dot(normalize(LightDir0), N);
#if SPECULAR //both
float NdotH0 = dot(normalize(HalfAngle0), N);
float4 Lit0 = lit(NdotL0,NdotH0,exponent0);
#else //just diffuse
float4 Lit0;
Lit0.y = saturate(NdotL0);
#endif
#elif SPECULAR //just specular
float NdotH0 = dot(normalize(HalfAngle0), N);
float4 Lit0;
Lit0.z = pow(saturate(NdotH0),exponent0);
#endif
#endif
#if LIGHT1
#if DIFFUSE
float NdotL1 = dot(normalize(LightDir1), N);
#if SPECULAR //both
float NdotH1 = dot(normalize(HalfAngle1), N);
float4 Lit1 = lit(NdotL1,NdotH1,exponent0);
#else //just diffuse
float4 Lit1;
Lit1.y = saturate(NdotL1);
#endif
#elif SPECULAR //just specular
float NdotH1 = dot(normalize(HalfAngle1), N);
float4 Lit1;
Lit1.z = pow(saturate(NdotH1),exponent0);
#endif
#endif
#if LIGHT2
#if DIFFUSE
float NdotL2 = dot(normalize(LightDir2), N);
#if SPECULAR //both
#if !ATTENUATION
float NdotH2 = dot(normalize(HalfAngle2), N);
float4 Lit2 = lit(NdotL2,NdotH2,exponent0);
#else
float4 Lit2;
Lit2.y = saturate(NdotL2);
#endif
#else //just diffuse
float4 Lit2;
Lit2.y = saturate(NdotL2);
#endif
#elif SPECULAR //just specular
#if !ATTENUATION
float NdotH2 = dot(normalize(HalfAngle2), N);
float4 Lit2;
Lit2.z = pow(saturate(NdotH2),exponent0);
#else
float4 Lit2;
Lit2 = float4(1,0,0,1);
#endif
#endif
#endif
oColor =
#if ATTENUATION //since usage rules specify it, we have at least light0 on with at least either
//diffuse or specular also on !
// - if you want no lighting, just textures, turn attenuation off!
//But yes, you can have diffusetex with just specular :)
//Note that you can't have specular of light2 with attenuation on. See docs.
// Final color formula with atten
// oColor = atten0 * (diffusetex * lightDiffuse0 * Lit0.y + lightSpecular0 * Lit0.z)
// atten1 * (diffusetex * lightDiffuse1 * Lit1.y + lightSpecular1 * Lit1.z)
// atten2 * (diffusetex * lightDiffuse2 * Lit2.y + lightSpecular2 * Lit2.z)
// + ambient;
#if !DIFFUSE //we start with the no diffuse just diffusetex case, here only spec is attenuated
#if DIFFUSE_TEXTURE
float4(diffusetex,1) +
#endif
#endif
// 1/(atten0.y + atten0.z*dist.x + atten0.w*dist.x*dist.x)* (
// use simpler formular instead: counts much in FPS!
#if !LIGHT0_IS_DIRECTIONAL
1/(1 + atten0.z*dist.x)* (
#else
( //for syntax
#endif
//we always have light0 on here, and spec0 or diffuse0 with it
#if SPECULAR
lightSpecular0 * Lit0.z
#if DIFFUSE
+
#else //light0 has only spec, light0 done
)
#endif
#endif
#if DIFFUSE
lightDiffuse0 * Lit0.y //without + sign, we are good at no specular case as well
#if DIFFUSE_TEXTURE
* float4(diffusetex,1)) //light0 done
#else
) //light0 done
#endif
#endif
#if LIGHT1 //optional, but if we have it, we have either diff1 or spec1, difftex can be 0/1
// + 1/(atten1.y + atten1.z*dist.y + atten1.w*dist.y*dist.y) * (
// use simpler formula instead
+ 1/(1 + atten1.z*dist.y) * (
#if SPECULAR
lightSpecular1 * Lit1.z
#if DIFFUSE
+
#else //light1 has only spec, light1 done
)
#endif
#endif
#if DIFFUSE
lightDiffuse1 * Lit1.y //without + sign here, we are good at no specular case as well
#if DIFFUSE_TEXTURE
* float4(diffusetex,1)) //light1 done
#else
) //light1 done
#endif
#endif
#endif
#if LIGHT2 //ditto goes for diff2, and difftex (no specular here)
// + 1/(atten2.y + atten2.z*dist.z + atten2.w*dist.z*dist.z) * (
// use simpler formula instead
+ 1/(1 + atten2.z*dist.z) * (
#if DIFFUSE
lightDiffuse2 * Lit2.y //without + sign here, we are good at no specular case as well
#if DIFFUSE_TEXTURE
* float4(diffusetex,1)) //light2 done
#else
) //light2 done
#endif
#endif
#endif
#else
// And wo. atten
// oColor = diffusetex
// * (lightDiffuse0 * Lit0.y + lightDiffuse1 * Lit1.y + lightDiffuse2 * Lit2.y)
// + lightSpecular0 * Lit0.z + lightSpecular1 * Lit1.z + lightSpecular2 * Lit2.z
// + ambient;
float4(0,0,0,0) //this is needed to simplify preprocessor stuff, no FPS cost :)
#if DIFFUSE_TEXTURE //at least diffuse texture, no lighting yet
+ float4(diffusetex,1)
#if DIFFUSE //modulate texture with lighting
*(
#if LIGHT0
lightDiffuse0 * Lit0.y
#endif
#if LIGHT1
+ lightDiffuse1 * Lit1.y
#endif
#if LIGHT2
+ lightDiffuse2 * Lit2.y
#endif
)
#endif
#elif DIFFUSE //just diffuse lighting, no modulation
#if LIGHT0
+ lightDiffuse0 * Lit0.y
#endif
#if LIGHT1
+ lightDiffuse1 * Lit1.y
#endif
#if LIGHT2
+ lightDiffuse2 * Lit2.y
#endif
#endif
#if SPECULAR
#if LIGHT0
+ lightSpecular0 * Lit0.z
#endif
#if LIGHT1
+ lightSpecular1 * Lit1.z
#endif
#if LIGHT2
+ lightSpecular2 * Lit2.z
#endif
#endif
#endif
#if AMBIENT
+ ambient
#endif
;
#if FADING
//WARNING: this will eat up all original/computed alpha!
oColor = float4(oColor.x, oColor.y, oColor.z, inFadeColor.w);
#endif
}
{CODE}