I struggle to get correct specular / reflection for two days, and finally find out that, normal come to shader in world space, and mtx_normal transform it back to local space.
following code is what I use at the very beginning without doubt nor second thought
attribute mediump vec3 normal;
uniform mediump mat4 mtx_normal;
varying mediump vec4 var_normal;
void main()
{
vec3 normalWorld = normalize((mtx_normal * vec4(normal, 0.0)).xyz);
//... calculate fresnel term, etc...
var_normal = vec4(normalWorld, fresnel);
//... frag color etc...
}
When I visualize normal vector on surface, I find that it gives local normal rather than world normal.
attribute mediump vec3 normal;
uniform mediump mat4 mtx_normal;
varying mediump vec4 var_normal;
void main()
{
// pass the normal directly, yield correct world normal instead
//... calculate fresnel term, etc...
var_normal = vec4(normal, fresnel);
//... frag color etc...
}
With this modification, my PBR implementation now render identically as Unity3D.
I wonder, is this by design or a bug?