天津23维预案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

401 lines
11 KiB

// Marmoset Skyshop
// Copyright 2013 Marmoset LLC
// http://marmoset.co
#ifndef MARMOSET_CORE_CGINC
#define MARMOSET_CORE_CGINC
#define INV_2PI 0.15915494309189533576888376337251
#define INV_2PIx2 0.31830988618379067153776752674502
//Linear - unity_ColorSpaceGrey.r is 0.19
//Gamma - unity_ColorSpaceGrey.r is 0.5
//linear ? 1 : 0 = (Grey - 0.5) / (0.19 - 0.5) = one clever MAD instruction
#define IS_LINEAR ((-3.22581*unity_ColorSpaceGrey.r) + 1.6129)
#define IS_GAMMA (( 3.22581*unity_ColorSpaceGrey.r) - 0.6129)
#ifdef MARMO_SPECULAR_IBL
uniform samplerCUBE _SpecCubeIBL;
#endif
uniform half4 _ExposureIBL; //IBL intensities
uniform half2 _ExposureLM; //IBL intensities when lightmapping
uniform half2 _UniformOcclusion; //Uniform diffuse and specular IBL occlusion terms
uniform float4x4 _SkyMatrix;
uniform float4x4 _InvSkyMatrix;
uniform float3 _SkySize;
uniform float3 _SkyMin;
uniform float3 _SkyMax;
uniform float3 _SH0;
uniform float3 _SH1;
uniform float3 _SH2;
uniform float3 _SH3;
uniform float3 _SH4;
uniform float3 _SH5;
uniform float3 _SH6;
uniform float3 _SH7;
uniform float3 _SH8;
#ifdef MARMO_SKY_BLEND
uniform float _BlendWeightIBL;
uniform half4 _ExposureIBL1; //IBL intensities
uniform half2 _ExposureLM1; //IBL intensities when lightmapping
uniform float4x4 _SkyMatrix1;
uniform float4x4 _InvSkyMatrix1;
uniform float3 _SkySize1;
uniform float3 _SkyMin1;
uniform float3 _SkyMax1;
#ifdef MARMO_SPECULAR_IBL
uniform samplerCUBE _SpecCubeIBL1;
#endif
uniform float3 _SH01;
uniform float3 _SH11;
uniform float3 _SH21;
uniform float3 _SH31;
uniform float3 _SH41;
uniform float3 _SH51;
uniform float3 _SH61;
uniform float3 _SH71;
uniform float3 _SH81;
#endif
//Color-correction
half3 toLinearApprox3(half3 c){ return c*c; }
half3 toLinear3(half3 c) { return pow(c,2.2); }
half toLinearFast1(half c) { half c2 = c*c; return dot(half2(0.7532,0.2468),half2(c2,c*c2)); }
half3 toLinearFast3(half3 c) { half3 c2 = c*c; return 0.7532*c2 + 0.2468*c*c2; }
half toGammaApprox1(half c) { return sqrt(c); }
half3 toGammaApprox3(half3 c) { return sqrt(c); }
half toGamma1(half c) { return pow(c,0.454545); }
half3 toGamma3(half3 c) { return pow(c,0.454545); }
half toGammaFast1(half c) {
c = 1.0 - c;
half c2 = c*c;
half3 c16 = half3(c2*c2,c2,c); //^4
c16.x *= c16.x; //^8
c16.x *= c16.x; //^16
c16 = half3(1.0,1.0,1.0)-c16;
return dot(half3(0.326999,0.249006,0.423995),c16);
}
half3 toGammaFast3(half3 c) {
half3 one = half3(1.0,1.0,1.0);
c = one - c;
half3 c2 = c*c;
half3 c16 = c2*c2; //^4
c16 *= c16; //^8
c16 *= c16; //^16
return 0.326999*(one-c16) + 0.249006*(one-c2) + 0.423995*(one-c);
}
//(1-t)a + t*a*a;
//a - t*a + t*a*a;
//a( 1-t + t*a);
//mul(a, mad(t,a,1-t)); //4 inst, 2 inst if t and 1-t are constants
//lerp(a, a*a, t); //4 inst, 3 inst if constant t
half toGammaAuto1(half a) { return a * ((a * IS_LINEAR) + IS_GAMMA); }
half3 toGammaAuto3(half3 a) { return a * ((a * IS_LINEAR.xxx) + IS_GAMMA.xxx); }
//(1-t)*sqrt(a) + t*a
//(1-s)*a + s*sqrt(a)
//a - s*a + s*sqrt(a)
//a - s*a + s*a/sqrt(a)
//a*(1-s+s*invsqrt(a))
//mul(a,mad(s,invsqrt(a),1-s))
//mul(a,mad(s,invsqrt(a),t)) //5 inst, 3 inst if constant t
//lerp(a*invsqrt(a), a, t) //5 inst, 4 if constant t
half toLinearAuto1(half a) { return a*(IS_GAMMA*rsqrt(a) + IS_LINEAR); }
half3 toLinearAuto3(half3 a) { return a*(IS_GAMMA.xxx*rsqrt(a) + IS_LINEAR.xxx); }
//approximations for the true, step-wise gamma curve used in sRGB compression
float linearTosRGB1( float c ) {
float sqrtc = sqrt( c ); //SQRT/MAD/MAD/MAD (accurate)
return (sqrtc - sqrtc*c) + c*(0.4672*c + 0.5328);
}
float3 linearTosRGB3( float3 c ) {
float3 sqrtc = sqrt( c ); //SQRT/MAD/MAD/MAD (accurate)
return (sqrtc - sqrtc*c) + c*(float3(0.4672,0.4672,0.4672)*c + float3(0.5328,0.5328,0.5328));
}
float4 linearTosRGB4( float4 c ) {
float4 sqrtc = sqrt( c ); //SQRT/MAD/MAD/MAD (accurate)
return (sqrtc - sqrtc*c) + c*(float4(0.4672,0.4672,0.4672,0.4672)*c + float4(0.5328,0.5328,0.5328,0.5328));
}
float sRGBToLinear1( float c ) {
return (c*c)*(c*0.2848 + 0.7152); //MAD/MUL/MUL (accurate)
}
float3 sRGBToLinear3( float3 c ) {
return (c*c)*(c*float3(0.2848,0.2848,0.2848) + float3(0.7152,0.7152,0.7152)); //MAD/MUL/MUL (accurate)
}
float4 sRGBToLinear4( float4 c ) {
return (c*c)*(c*float4(0.2848,0.2848,0.2848,0.2848) + float4(0.7152,0.7152,0.7152,0.7152)); //MAD/MUL/MUL (accurate)
}
float3 mulVec3( float4x4 m, float3 v ) {
return float3(dot(m[0].xyz,v.xyz),
dot(m[1].xyz,v.xyz),
dot(m[2].xyz,v.xyz));
}
float3 mulPoint3( float4x4 m, float3 p ) {
float4 v = float4(p.x,p.y,p.z,1.0);
return float3(dot(m[0],v),
dot(m[1],v),
dot(m[2],v));
}
float3 transposeMulVec3( float4x4 m, float3 v ) {
return m[0].xyz*v.x + (m[1].xyz*v.y + (m[2].xyz*v.z));
}
float3 transposeMulVec3( float3x3 m, float3 v ) {
return m[0].xyz*v.x + (m[1].xyz*v.y + (m[2].xyz*v.z));
}
float3 transposePoint3( float4x4 m, float3 p ) {
return m[0].xyz*p.x + (m[1].xyz*p.y + (m[2].xyz*p.z + m[3].xyz));
}
half3 fromRGBM(half4 c) {
c.a *= 6.0;
return c.rgb * lerp(c.a, toLinearFast1(c.a), IS_LINEAR);
}
half3 diffCubeLookup(samplerCUBE diffCube, float3 worldNormal) {
half4 diff = texCUBE(diffCube, worldNormal);
return fromRGBM(diff);
}
half3 specCubeLookup(samplerCUBE specCube, float3 worldRefl) {
half4 spec = texCUBE(specCube, worldRefl);
return fromRGBM(spec);
}
half3 glossCubeLookup(samplerCUBE specCube, float3 worldRefl, float glossLod) {
#ifdef MARMO_BIAS_GLOSS
half4 lookup = half4(worldRefl,glossLod);
half4 spec = texCUBEbias(specCube, lookup);
#else
half4 lookup = half4(worldRefl,glossLod);
half4 spec = texCUBElod(specCube, lookup);
#endif
return fromRGBM(spec);
}
half glossLOD(half glossMap, half shininess) {
glossMap = 1.0-glossMap;
glossMap = 1.0-(glossMap*glossMap);
return 7.0 + glossMap - (shininess*glossMap);
}
half glossExponent(half glossLod) {
return exp2(8.0-glossLod);
}
//returns 1/spec. function integral
float specEnergyScalar(float gloss) {
return (gloss*INV_2PI) + INV_2PIx2;
}
half splineFresnel(float3 N, float3 E, half specIntensity, half fresnel) {
half factor = 1.0-saturate(dot(N,E));
half factor3 = factor*factor*factor;
//a spline between 1, factor, and factor^3
half3 p = half3(1.0, factor, factor3);
half2 t = half2(1.0-fresnel,fresnel);
p.x = dot(p.xy,t);
p.y = dot(p.yz,t);
factor = 0.05 + 0.95 * dot(p.xy,t);
factor *= specIntensity;
//The math above is performed in linear space. If rendering in gamma space,
//fresnel*specInt needs to be applied in gamma-space.
// Note: specInt is also a linear value, it comes from a slider.
factor = lerp(sqrt(factor), factor, IS_LINEAR);
return factor;
}
half fastFresnel(float3 N, float3 E, half specIntensity, half fresnel) {
//fresnel math performed in gamma space
half factor = 1.0-saturate(dot(N,E));
factor *= 0.5 + 0.5*factor;
factor = 0.15 + factor*0.85;
factor = lerp(1.0, factor, fresnel);
factor = specIntensity * factor;
factor = lerp(factor, factor*factor, IS_LINEAR);
return factor;
}
float3 skyRotate(uniform float4x4 skyMatrix, float3 R) {
#ifdef MARMO_SKY_ROTATION
R = transposeMulVec3(skyMatrix,R);
#endif
return R;
}
float3 skyProject(uniform float4x4 skyMatrix, uniform float4x4 invSkyMatrix, uniform float3 skyMin, uniform float3 skyMax, float3 worldPos, float3 R) {
#ifdef MARMO_BOX_PROJECTION
//box projection happens in sky-space
#ifdef MARMO_SKY_ROTATION
R = transposeMulVec3(skyMatrix,R).xyz; //HACK: mulVec3 is mul(transpose(_sky))
#endif
float3 invR = 1.0/R;
#ifdef MARMO_SKY_ROTATION
float3 P = mulPoint3(invSkyMatrix,worldPos);
#else
float3 P = worldPos - skyMatrix[3].xyz;
#endif
float3 rbminmax = lerp(skyMin, skyMax, saturate(R*1000000.0));
rbminmax = (rbminmax - P.xyz) * invR;
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
//R in projected sky space
return (R*fa) + P.xyz;
#else
#ifdef MARMO_SKY_ROTATION
R = transposeMulVec3(skyMatrix,R);
#endif
return R;
#endif
}
//converts linear, HDR color to RGBM encoded data, ready for screen output
float4 HDRtoRGBM(float4 color) {
float toLinear = 2.2;
float toGamma = 1.0/2.2;
color.rgb = pow(color.rgb, toGamma); //RGBM gamma compression is 1/2.2
color *= 1.0/6.0;
float m = max(max(color.r,color.g),color.b);
m = saturate(m);
m = ceil(m*255.0)/255.0;
if( m > 0.0 ) {
float inv_m = 1.0/m;
color.rgb = saturate(color.rgb*inv_m);
color.a = m;
} else {
color = half4(0.0,0.0,0.0,0.0);
}
return color;
}
float3 SHLookup(float3 dir) {
//l = 0 band (constant)
float3 result = _SH0.xyz;
//l = 1 band
result += _SH1.xyz * dir.y;
result += _SH2.xyz * dir.z;
result += _SH3.xyz * dir.x;
//l = 2 band
float3 swz = dir.yyz * dir.xzx;
result += _SH4.xyz * swz.x;
result += _SH5.xyz * swz.y;
result += _SH7.xyz * swz.z;
float3 sqr = dir * dir;
result += _SH6.xyz * ( 3.0*sqr.z - 1.0 );
result += _SH8.xyz * ( sqr.x - sqr.y );
return abs(result);
}
void SHLookup(float3 dir, out float3 band0, out float3 band1, out float3 band2) {
//l = 0 band (constant)
band0 = _SH0.xyz;
//l = 1 band
band1 = _SH1.xyz * dir.y;
band1 += _SH2.xyz * dir.z;
band1 += _SH3.xyz * dir.x;
//l = 2 band
float3 swz = dir.yyz * dir.xzx;
band2 = _SH4.xyz * swz.x;
band2 += _SH5.xyz * swz.y;
band2 += _SH7.xyz * swz.z;
float3 sqr = dir * dir;
band2 += _SH6.xyz * ( 3.0*sqr.z - 1.0 );
band2 += _SH8.xyz * ( sqr.x - sqr.y );
}
#ifdef MARMO_SKY_BLEND
float3 SHLookup1(float3 dir) {
//l = 0 band (constant)
float3 result = _SH01.xyz;
//l = 1 band
result += _SH11.xyz * dir.y;
result += _SH21.xyz * dir.z;
result += _SH31.xyz * dir.x;
//l = 2 band
float3 swz = dir.yyz * dir.xzx;
result += _SH41.xyz * swz.x;
result += _SH51.xyz * swz.y;
result += _SH71.xyz * swz.z;
float3 sqr = dir * dir;
result += _SH61.xyz * ( 3.0*sqr.z - 1.0 );
result += _SH81.xyz * ( sqr.x - sqr.y );
return abs(result);
}
void SHLookup1(float3 dir, out float3 band0, out float3 band1, out float3 band2) {
//l = 0 band (constant)
band0 = _SH01.xyz;
//l = 1 band
band1 = _SH11.xyz * dir.y;
band1 += _SH21.xyz * dir.z;
band1 += _SH31.xyz * dir.x;
//l = 2 band
float3 swz = dir.yyz * dir.xzx;
band2 = _SH41.xyz * swz.x;
band2 += _SH51.xyz * swz.y;
band2 += _SH71.xyz * swz.z;
float3 sqr = dir * dir;
band2 += _SH61.xyz * ( 3.0*sqr.z - 1.0 );
band2 += _SH81.xyz * ( sqr.x - sqr.y );
}
#endif
float3 SHLookupUnity(float3 dir) {
return ShadeSH9(half4(dir.x, dir.y, dir.z,1.0));
}
void SHLookupUnity(float3 dir, out float3 band0, out float3 band1, out float3 band2) {
//constant term
band0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
// Linear term
band1.r = dot(unity_SHAr.xyz, dir.xyz);
band1.g = dot(unity_SHAg.xyz, dir.xyz);
band1.b = dot(unity_SHAb.xyz, dir.xyz);
// 4 of the quadratic polynomials
half4 vB = dir.xyzz * dir.yzzx;
band2.r = dot(unity_SHBr,vB);
band2.g = dot(unity_SHBg,vB);
band2.b = dot(unity_SHBb,vB);
// Final quadratic polynomial
float vC = dir.x*dir.x - dir.y*dir.y;
band2 += unity_SHC.rgb * vC;
}
float3 SHConvolve(float3 band0, float3 band1, float3 band2, float3 weight) {
float3 conv1 = lerp( float3(1.0,1.0,1.0), float3(0.6667,0.6667,0.6667), weight);
float3 conv2 = lerp( float3(1.0,1.0,1.0), float3(0.25,0.25,0.25), weight);
conv1 = lerp(conv1, conv1*conv1, weight);
conv2 = lerp(conv2, conv2*conv2, weight);
return abs(band0 + band1*conv1 + band2*conv2);
}
#endif