hi guys, i'm trying to emulate the GPU Gems 3:14 specularity in unity, here's the CG shader i've gotten so far, but i'm getting errors.
CGPROGRAM
#pragma surface surf Lambert
#include "UnityCG.cginc"
#pragma target 3.0
sampler2D _Beckmann;
float _Roughness;
float _Spec;
float fresnelReflectance(SurfaceOutput s, half3 lightDir,half3 viewDir)
{
half H = dot (s.Normal, lightDir);
float base = 1.0 - dot( viewDir, H );
float exponential = pow( base, 5.0 );
return exponential + 0.028 * ( 1.0 - exponential );
}
float PHBeckmann(SurfaceOutput s, half3 lightDir, float _Roughness)
{
half H = dot(s.Normal, lightDir);
float ndoth = dot(s.Normal, H);
float alpha = acos(dot(s.Normal, H));
float ta = tan(alpha);
float val = 1.0/(_Roughness*_Roughness*pow(ndoth,4.0))*exp(-(ta*ta)/(_Roughness*_Roughness));
return val;
}
float KS_Skin_Specular( SurfaceOutput s, float3 lightDir, float3 viewDir)
{
float result = 0.0;
float ndotl = dot( s.Normal, lightDir );
if( ndotl > 0.0 )
{
float3 h = (lightDir + viewDir);
float3 H = normalize(h);
float ndoth = dot( s.Normal, H );
float look = tex2D(_Beckmann,float2(ndoth,_Roughness));
float PH = pow( 2.0*look, 10.0 );
float F = fresnelReflectance( H, viewDir, 0.028 );
float frSpec = max( PH * F / dot( h, h ), 0 );
result = ndotl * _Spec * frSpec;
}
return result;
}
the errors i'm getting are:
Shader error in 'Custom/BDRF_Testshader': Program 'vert_surf', 'fresnelReflectance': cannot implicitly convert from 'float3' to 'struct SurfaceOutput' (compiling for d3d11)
now, i kind of understand it. it's telling me that it can't turn a float 3 (in this case, the viewDir and lightDir float3's) into a float. so i know what the error IS, i'm just not sure WHERE it is, like which part of the math i fucked up.
Replies
return float(my math);
Try passing just the normal in rather than the whole struct? I started to try to work through your shader but I'm not too familiar with the unity bindings etc. So I'm not sure I can be a lot of help.
I might go and read up on them and get a handle on the shaders though. Thanks for inspiring me! ;-)
take the simple specular examle from here: http://docs.unity3d.com/Documentation/Components/SL-SurfaceShaderLightingExamples.html
and splice in your skin spec functions, it should work?
good luck!
it's telling me there are syntax errors at lines which i've indicated in the above code. but i can't see them for the life of me.
float FS = max(0.0, KS_Skin_Specular);
here you're calling functions like variables which is such a fundamental mistake i'm honestly impressed you got this far.
float ndoth = dot(_Normal, H);
float spec = ndotl * _Spec * frSpec;
not only are you calling a function as a variable here, but you're also calling a sampler(_Normal, _Spec) directly. this doesn't work. look into what tex2D() actually does. hopefully an example clears this up.
float3 halfvector = H; <-- this is wrong
float3 halfvector = H(lightDir, viewDir); <-- this is correct
float ndoth = dot(tex2D(_Normal,UVs).xyz, H(lightDir, viewDir);
in your actual shader you'll probably call s.Normal instead of tex2D() because of the way surface shaders are structured, and "UVs" would be replaced with your actual uv:s.
I strongly suggest you to read through the shader documents in the unity manual, it's fairly easy to follow along (with a lot of examples) and covers a lot of ground.
edit: and the shader compiler's error messages have always been really cryptic and confusing. a lot of the time the messages and line numbers it spits out are completely useless. unfortunately.
http://www.polycount.com/forum/showthread.php?t=96874
Maybe that will help you out. One thing I noticed - the inputs seem to be per vertex not per pixel, not sure how to fix that in unity - worth googling to find out.
As equil said, there's a few bloopers in your stuff there, so it's worth maybe attacking it in 2 stages - get something working in cg in a framework you are familiar with, and then deal with the unity plumbing as a separate task. It might make things simpler or go smoother.
Good luck!
managed to get it working for the most part.