謎解きはディナーのあとで
みたいなタイトルを目指しました。
HTML5カンファレンスでShaderの話をさせてもらう機会をいただきまして、
その時にDEMOをするのにShdr Editorというオンラインエディタを使いました。
http://shdr.bkcore.com/
控え室でWebGLな人たちと話をしていた時、DEMOの様子を少し見せたところ、
@kyasbal_1994 に、「normalize
はフラグメントシェーダでした方がいいよ」と教えてもらった。
Shdrのデフォルトコードにそれは含まれている
precision highp float;
attribute vec3 position;
attribute vec3 normal;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fNormal;
varying vec3 fPosition;
void main()
{
fNormal = normalize(normalMatrix * normal); // <-- ここ
vec4 pos = modelViewMatrix * vec4(position, 1.0);
fPosition = pos.xyz;
gl_Position = projectionMatrix * pos;
}
ぜったいにバーテックスシェーダで normalize
してはいけないということではなくて、
varying
でフラグメントジェーダに渡す前に normalize
しても線形補間されたあとのベクトルの長さは 1.0
ではなくなっているということでして。
たしかに、 normalize
されたベクトルの length
で色を指定してみると真っ白になるはずがそうはならない。
precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;
void main()
{
// vec3 normal = normalize(fNormal);// <-- これだと真っ白になる
vec3 normal = fNormal;
gl_FragColor = vec4(length(normal));
}
実際の例はこちら
https://goo.gl/RsdhSN
数値的には微妙な差でも色々重ねがけしていくと問題になることがあるらしい。