自学内容网 自学内容网

THREE.JS Blinn–Phong反射模型 高光shader

Blinn–Phong reflection model

平滑着色平直着色
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述
顶点
// 法线
vNormal = normalMatrix * normal;
vNormal = normalize( vNormal );
// 点光位置
vPointLightPosition = (viewMatrix * vec4( pointLightPosition, 1.0 )).xyz;
//顶点位置
vec3 transformed = vec3( position );
vec4 mvPosition = vec4( transformed, 1.0 );
mvPosition = modelViewMatrix * mvPosition;
vViewPosition = - mvPosition.xyz;

片元
不同着色方式法线设置

#ifdef FLAT_SHADED

vec3 fdx = dFdx( vViewPosition );
vec3 fdy = dFdy( vViewPosition );
vec3 normal = normalize( cross( fdx, fdy ) );

#else

vec3 normal =  vNormal ;
normal = normalize( vNormal );

#endif

vec3 geometryPosition = - vViewPosition;
vec3 geometryNormal = normal;
vec3 geometryViewDir = normalize( vViewPosition );

//光线方向
vec3 lVector = vPointLightPosition - geometryPosition;
vec3 lightDirection = normalize( lVector );
//直接反射高光颜色
vec3 phongColor = BRDF_BlinnPhong( lightDirection, geometryViewDir, geometryNormal, vec3(1), 30.);

全部代码

import * as THREE from "three";

const bsdfs_glsl = /* glsl */ `

    float pow2( const in float x ) { return x*x; }
    vec3 pow2( const in vec3 x ) { return x*x; }
    float pow4( const in float x ) { float x2 = x*x; return x2*x2; }

    // 距离衰减
    float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
            
        float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );

        if ( cutoffDistance > 0.0 ) {

            distanceFalloff *= pow2( clamp( 1.0 - pow4( lightDistance / cutoffDistance ) ,0. ,1.) );

        }

        return distanceFalloff;

    }

    // common.glsl.js
    vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {

        // Original approximation by Christophe Schlick '94
        // float fresnel = pow( 1.0 - dotVH, 5.0 );

        // Optimized variant (presented by Epic at SIGGRAPH '13)
        // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
        float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );

        return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );

    }

    float F_Schlick( const in float f0, const in float f90, const in float dotVH ) {

        // Original approximation by Christophe Schlick '94
        // float fresnel = pow( 1.0 - dotVH, 5.0 );

        // Optimized variant (presented by Epic at SIGGRAPH '13)
        // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
        float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );

        return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );

    }

    // bsdfs.glsl.js

    float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {

        // geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)
        return 0.25;

    }

    float D_BlinnPhong( const in float shininess, const in float dotNH ) {

        return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );

    }

    vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {

        vec3 halfDir = normalize( lightDir + viewDir );

        float dotNH = clamp( dot( normal, halfDir ) ,0.,1.);
        float dotVH = clamp( dot( viewDir, halfDir ) ,0.,1.);

        vec3 F = F_Schlick( specularColor, 1.0, dotVH );

        float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );

        float D = D_BlinnPhong( shininess, dotNH );

        return F * ( G * D );

    }
`;

export class SpecularShaderMaterial extends THREE.ShaderMaterial {
    constructor(
        params?: ConstructorParameters<typeof THREE.ShaderMaterial>[0] & {
            pointLightPosition: THREE.Vector3;
            pointLightDistance: number;
            pointLightDecay: number;
        }
    ) {
        super({
            uniforms: {
                pointLightPosition: {
                    value: params!.pointLightPosition,
                },
                pointLightDistance: {
                    value: params?.pointLightDistance ?? 100,
                },
                pointLightDecay: {
                    value: params?.pointLightDecay ?? 2,
                },
            },
            defines: {
                RECIPROCAL_PI: 1 / Math.PI,
                // 平直着色 关闭则 平滑着色
                FLAT_SHADED: false,
            },
            vertexShader: /* glsl */ `
                varying vec3 vNormal;
                varying vec3 vertexPosition;
                uniform vec3 pointLightPosition;
                varying vec3 vPointLightPosition;
                
                varying vec3 vViewPosition;

                void main() {

                    vNormal = normalMatrix * normal;
                    vNormal = normalize( vNormal );

                    vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
                    gl_Position = projectionMatrix * modelViewPosition;
                    vertexPosition = modelViewPosition.xyz;
                    vPointLightPosition = (viewMatrix * vec4( pointLightPosition, 1.0 )).xyz;

                    vec3 transformed = vec3( position );

                    vec4 mvPosition = vec4( transformed, 1.0 );
                    
                    mvPosition = modelViewMatrix * mvPosition;

                vViewPosition = - mvPosition.xyz;

                }`,
            fragmentShader: /* glsl */ `
                varying vec3 vNormal;               
                varying vec3 vertexPosition;
                varying vec3 vPointLightPosition;
                
                uniform vec3 pointLightPosition;
                uniform float pointLightDistance;
                uniform float pointLightDecay;
                varying vec3 vViewPosition;

                ${bsdfs_glsl}

                void main() {

                    #ifdef FLAT_SHADED

                        vec3 fdx = dFdx( vViewPosition );
                        vec3 fdy = dFdy( vViewPosition );
                        vec3 normal = normalize( cross( fdx, fdy ) );

                    #else

                        vec3 normal =  vNormal ;
                        normal = normalize( vNormal );

                    #endif

                    vec3 geometryPosition = - vViewPosition;
                    vec3 geometryNormal = normal;
                    vec3 geometryViewDir = normalize( vViewPosition );

                    // 取自 getPointLightInfo
                    // vec3 lVector = pointLightPosition - geometryPosition;
                    vec3 lVector = vPointLightPosition - geometryPosition;
            
                    vec3 lightDirection = normalize( lVector );
            
                    float lightDistance = length( lVector );
            
                    vec3 lightColor = vec3( 1. );
                    lightColor *= getDistanceAttenuation( lightDistance, pointLightDistance, pointLightDecay );

                    // 取自 RE_Direct_BlinnPhong
                    float dotNL = clamp( dot( geometryNormal, lightDirection ) ,0. ,1. );
                    vec3 irradiance = dotNL * lightColor;
                
                    // vec3 reflectedLightDirectSpecular = irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;
                    vec3 phongColor = BRDF_BlinnPhong( lightDirection, geometryViewDir, geometryNormal, vec3(1), 30.);

                    // gl_FragColor = vec4(vec3( irradiance ) , 1. );
                    gl_FragColor = vec4(vec3( phongColor ) , 1. );
                    // gl_FragColor = vec4(vec3( lightDirection ) , 1. );
                    // gl_FragColor = vec4(vec3( pointLightPosition ) , 1. );
                    // gl_FragColor = vec4(vec3( vPointLightPosition ) , 1. );
                    // gl_FragColor = vec4(vec3( normal ) , 1. );
                    // gl_FragColor = vec4(vec3( lightColor ) , 1. );
                    // gl_FragColor = vec4(vec3( irradiance ) , 1. );
                }`,
        });
    }
}


原文地址:https://blog.csdn.net/printf_hello/article/details/142681800

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!