我正在尝试创建一个着色器,在Three.js中产生发光的光晕效果。我的当前尝试可以在这里实时查看:http://stemkoski.github.io/Three.js/Shader-Halo.html
目前的着色器代码如下:
<script id="vertexShader" type="x-shader/x-vertex">
varying vec3 vNormal;
void main()
{
vNormal = normalize( normalMatrix * normal );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-vertex">
varying vec3 vNormal;
void main()
{
float intensity = pow( 0.7 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) ), 4.0 );
gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ) * intensity;
}
</script>
只要物体保持在场景中心,这种方法就能正常工作。但是在缩放或平移后,光晕效果似乎会改变强度或看起来不对称。
我认为我理解了数学上的原因 - 在这段代码中,发光效果的强度取决于网格法线向量的z坐标,因为那是面向观察者的向量,所以我应该在计算强度之前对(0,0,1)进行类似的转换。
因此,我得出了以下结论:
<script id="vertexShader" type="x-shader/x-vertex">
varying vec3 vNormal;
varying vec4 vector;
void main()
{
vNormal = normalize( normalMatrix * normal );
vector = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 1.0, 0.0 );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-vertex">
varying vec3 vNormal;
varying vec4 vector;
void main()
{
vec4 v = vec4( vNormal, 0.0 );
float intensity = pow( 0.7 - dot( v, vector ), 4.0 );
gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ) * intensity;
}
</script>
即使在原点,它看起来与我的原始着色器完全不同,并且随着我缩放和平移场景而不断变化。我很困惑。有人知道如何正确转换法向量(或应进行哪些其他更改),以便此着色器产生的外观在缩放/平移场景时不会改变吗?
[更新]
似乎在http://john-chapman-graphics.blogspot.com/2013/01/good-enough-volumetrics-for-spotlights.html上有一个有希望的线索。
特别地,
边缘...需要以某种方式变软,这就是顶点法线发挥作用的地方。我们可以使用视图空间法线(cnorm)与视图向量(规范化的片段位置cpos)的点积作为度量描述当前片段距离边缘有多近。
有人知道计算视图空间法线和视图向量的代码吗?