three.js ShaderMaterial FlatShading

标签 three.js glsl

我正在编写自定义 ShaderMaterial 并决定包含灯光和雾。到目前为止一切顺利,我得到了与 three.js 集成的着色器构建它的雾、环境光和点光(它符合我的目的)。

但是,我得到的阴影是平滑的,而不是平坦的。在你们决定建议将 shading: THREE.FlatShading 标志添加到 ShaderMaterial 之前,请记住这是一个自定义着色器,因此不会真正执行任何操作。

由于 FlatShading 是通过计算三角形质心并根据该向量填充所有颜色来完成的,我认为使用三角形顶点的法线可以解决问题..显然它确实...这是一种正确的方式吗一个 FlatShading 光,其中三角形内的所有像素都具有 1 种单一颜色?如果是这样,我错过了什么?

这是我在 CoffeeScript 中的着色器

类 SomeShader

constructor: ->

    @defines = {}

    @uniforms = THREE.UniformsUtils.merge [
        THREE.UniformsLib['fog']
        THREE.UniformsLib['lights']
        {
            color: { type: 'c', value: new THREE.Color(0xffffff) }
        }
    ]

    @vertex = [
        'uniform vec3 ambientLightColor;'
        '#if MAX_POINT_LIGHTS > 0'
        '   uniform vec3 pointLightColor[MAX_POINT_LIGHTS];'
        '   uniform vec3 pointLightPosition[MAX_POINT_LIGHTS];'
        '   uniform float pointLightDistance[MAX_POINT_LIGHTS];'
        '#endif'

        'uniform vec3 color;'
        'varying vec4 v_color;'

        'void main() {'
        # lights
        '   vec3 norm = normalMatrix * normal;'
        '   vec3 pos = (modelViewMatrix * vec4(position-norm, 1.0 )).xyz;'
        '   vec3 outgoingLight = vec3(1.);'
        '   vec4 addedLights = vec4(0., 0., 0., 1.);'
        '   #if MAX_POINT_LIGHTS > 0'
        '   for(int l = 0; l < MAX_POINT_LIGHTS; l++) {'
        '       vec3 lightDirection = normalize(pos - pointLightPosition[l]);'
        '       addedLights.rgb += clamp(dot(-lightDirection, norm), 0.0, 1.0) * pointLightColor[l];'
        '   }'
        '   #endif'
        '   addedLights += vec4(ambientLightColor, 1.);'
        '   v_color = vec4(outgoingLight, 1.) * addedLights;'
        '   gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);'
        '}'
    ].join '\n'

    @fragment = [
        THREE.ShaderChunk['fog_pars_fragment']

        'varying vec4 v_color;'

        'void main() {'
        '   vec3 outgoingLight = vec3( 1. );'
            THREE.ShaderChunk['fog_fragment']
        '   gl_FragColor = v_color * vec4(outgoingLight, 1.);'
        '}'
    ].join '\n'

最佳答案

您正在使用 ShaderMaterial 并且您正在使用噪声函数置换顶点着色器中的顶点。您还想重新计算顶点法线,以便着色是平坦的——即多面体。

为此,您需要在片段着色器中使用屏幕空间导数计算新法线,并在片段着色器中进行光照计算。

因此,在您的顶点着色器中,计算以下 varying:

varying vec3 vViewPosition;

vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );
vViewPosition = - mvPosition.xyz; // vector from vertex to camera

然后,在片段着色器中,使用屏幕空间导数计算法线:

normal = normalize( cross( dFdx( vViewPosition ), dFdy( vViewPosition ) ) );

现在,使用您的光照模型计算片段着色器中的着色。

three.js r.73

关于three.js ShaderMaterial FlatShading,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33094496/

相关文章:

javascript - 如何检测被其他面孔隐藏的 3D 形状的面孔(从 Angular 看不到)?

javascript - 如何重置 three.js 时钟?

javascript - 基于 BoxBufferGeometry 编写自定义 Shape Geometry

c++ - "Empty"使用 openGL 渲染

javascript - 如何在模型 View 投影广告牌顶点着色器中保留旋转和缩放变换?

opengl-es - 为 OpenGL ES 2.0 中的数组索引提供一个整数?

opengl - 使用 OpenGL/GLSL 的降尺度(下采样)技术实现光晕效果

javascript - 具有相似属性的简单功能

three.js - 将 GLSL 3 ES 与 Three.js 结合使用

javascript - Three.js 纹理模型未正确应用于对象