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

本文是小编为大家收集整理的关于Three.js-shader的光晕效果代码,法线需要转换的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在尝试创建一个着色器来产生三分之二的发光光环效果.我目前的尝试是在这里进行的: http://stemkoskoski.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>

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

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

[更新]

似乎有一个有希望的领导 .blogspot.com/2013/01/good-Em-Em-Em-Enough-volumetrics-for spotlights.html

特别是

边缘...需要以某种方式软化,这就是顶点正态进入的地方.我们可以将视图空间(CNORM)的点乘积与视图向量(归一化片段位置,CPOS)一起使用为一个指标描述了如何靠近边缘...当前片段是如何的.

有人知道计算视图空间正常和视图向量的代码吗?

推荐答案

弄清楚了!

在上面的代码中,vNormal是正常的顶点.要获取视图向量,请在着色器上添加​​一个统一,其值是网格位置和相机位置之间的差异. (从理论上讲,值应该是每个顶点的位置和相机位置之间的区别,但这对于我的目的足够接近.)

有关实施,请查看:/three.js/shader-glow.html

本文地址:https://www.itbaoku.cn/post/2091101.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

The shader code is currently:

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

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.

Thus I arrived at

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

[Update]

There seems to be a promising lead at http://john-chapman-graphics.blogspot.com/2013/01/good-enough-volumetrics-for-spotlights.html

In particular,

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?

推荐答案

Figured it out!

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

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