Three.js - 光晕效果的着色器代码,法线需要转换

时间:2013-07-03 18:41:14

标签: three.js glsl shader fragment-shader vertex-shader

我正在尝试创建一个着色器以在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)作为描述如何靠近边缘的度量...当前片段是。

有人知道用于计算视图空间法线和视图向量的代码吗?

1 个答案:

答案 0 :(得分:5)

想出来了!

在上面的代码中,vNormal是顶点法线。要获取视图矢量,请为着色器添加一个制服,其值是网格位置和摄像机位置之间的差值。 (理论上,值应该是每个顶点位置和摄像机位置之间的差异,但这对我的目的而言足够接近。)

有关实施,请查看:http://stemkoski.github.io/Three.js/Shader-Glow.html