Three.js-具有光晕效果的着色器代码,法线需要转换 [英] Three.js - shader code for halo effect, normals need transformation

查看:411
本文介绍了Three.js-具有光晕效果的着色器代码,法线需要转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个着色器以在Three.js中产生发光的光晕效果.我当前的尝试在此处进行: http://stemkoski.github.io/Three. js/Shader-Halo.html

I am attempting to create a shader to produce a glowing halo effect in Three.js. My current attempt is live here: 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>

如果对象保持在场景中心,则此方法工作正常.缩放或平移后,光晕效果似乎分别改变强度或看起来偏斜.

This works fine provided the object remains at the center of the scene. After zooming or panning, the halo effect appears to change intensity or looks lopsided, respectively.

我想我理解为什么这是数学上的原因-在此代码中,发光效果的强度由法向矢量与网格的z坐标确定,因为那是面向观察者的矢量,依此类推在计算强度之前,我应该以某种方式对(0,0,1)应用类似的变换.

I think I understand why this is, mathematically -- in this code, the intensity of the glow effect is determined by the z-coordinate of the normal vector to the mesh, because that is the vector facing the viewer, and so I should somehow apply a similar transformation to (0,0,1) before calculating the intensity.

因此我到达了

<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>

即使在原点时也看起来与原始着色器完全不同,并且在我缩放和平移场景时会继续改变外观.

which looks completely different from my original shader even when at the origin, and continues to change appearance as I zoom and pan the scene.

我很茫然.是否有人知道如何正确变换法向矢量(或应该进行其他更改),以便在缩放/平移场景时此着色器产生的外观不会改变?

I am at a loss. Does anybody know how to transform the normal vector correctly (or what other change(s) should be made) so that the appearance produced by this shader does not change when zooming/panning the scene?

[更新]

http://john-chapman-graphics .blogspot.com/2013/01/good-enough-volumetrics-for-spotlights.html

尤其是

需要以某种方式软化边缘...,这就是顶点法线的所在.我们可以将视图空间法线(cnorm)的点积与视图矢量(归一化片段位置,cpos)一起使用,描述当前片段离边缘有多近的度量.

The edges ... need to be softened somehow, and that's where the vertex normals come in. We can use the dot product of the view space normal (cnorm) with the view vector (the normalised fragment position, cpos) as a metric describing how how near to the edge ... the current fragment is.

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

Does anybody know the code for calculating the view space normal and the view vector?

推荐答案

想通了!

在我上面的代码中,vNormal是顶点法线.要获取视图矢量,请向着色器添加一个统一体,该统一体的值是网格位置与摄影机位置之间的差. (理论上,该值应该是每个顶点位置和相机位置之间的差,但这对于我来说已经足够接近了.)

In my code above, vNormal was the vertex normal. To get the view vector, add a uniform to the shader whose value is the difference between the mesh's position and the camera's position. (In theory, the value should be the difference between each vertex's position and the camera's position, but this was close enough for my purposes.)

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

For an implementation, check out: http://stemkoski.github.io/Three.js/Shader-Glow.html

这篇关于Three.js-具有光晕效果的着色器代码,法线需要转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆