【PBR】THREE MeshPhongMaterial分析

1.顶点着色

export default /* glsl */`
#define PHONG

varying vec3 vViewPosition;

#ifndef FLAT_SHADED

	varying vec3 vNormal;

#endif

#include <common>
#include <uv_pars_vertex>
#include <uv2_pars_vertex>
#include <displacementmap_pars_vertex>
#include <envmap_pars_vertex>
#include <color_pars_vertex>
#include <fog_pars_vertex>
#include <morphtarget_pars_vertex>
#include <skinning_pars_vertex>
#include <shadowmap_pars_vertex>
#include <logdepthbuf_pars_vertex>
#include <clipping_planes_pars_vertex>

void main() {

	#include <uv_vertex>
	#include <uv2_vertex>
	#include <color_vertex>

	#include <beginnormal_vertex>
	#include <morphnormal_vertex>
	#include <skinbase_vertex>
	#include <skinnormal_vertex>
	#include <defaultnormal_vertex>

#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED

	vNormal = normalize( transformedNormal );

#endif

	#include <begin_vertex>
	//内容:
	//vec3 transformed = vec3( position );
	//
	#include <morphtarget_vertex>
	#include <skinning_vertex>
	#include <displacementmap_vertex>
	#include <project_vertex>
	//内容:
    //vec4 mvPosition = vec4( transformed, 1.0 ); 
	//mvPosition = modelViewMatrix * mvPosition;
	//gl_Position = projectionMatrix * mvPosition;
	//
	#include <logdepthbuf_vertex>
	#include <clipping_planes_vertex>

	vViewPosition = - mvPosition.xyz; 


	#include <worldpos_vertex>
	// 内容:求世界坐标
	// vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
	//
	#include <envmap_vertex>
	#include <shadowmap_vertex>
	#include <fog_vertex>

}
`;

2.片元着色

#define PHONG
uniform vec3 diffuse;
uniform vec3 emissive;
uniform vec3 specular;
uniform float shininess;
uniform float opacity;

#include <color_pars_fragment>

#ifdef USE_COLOR
	varying vec3 vColor;
#endif

#include <uv_pars_fragment>

#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )
	varying vec2 vUv;
#endif

#include <map_pars_fragment>


#ifdef USE_MAP
	uniform sampler2D map;
#endif

//下面三个比较重要

#include <双向反射函数>


#include <lights_pars_begin>


 内容:初始化各类灯光及其根据灯光位置和顶点的距离 返回该顶点实际灯光的强度和颜色
uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight )

uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
void getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight )

uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];
void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  )

uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];

#include <lights_phong_pars_fragment>


varying vec3 vViewPosition;
struct BlinnPhongMaterial {
	vec3	diffuseColor;
	vec3	specularColor;
	float	specularShininess;
	float	specularStrength;
};

void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );//saturate是clamp0-1
	vec3 irradiance = dotNL * directLight.color;
	#ifndef PHYSICALLY_CORRECT_LIGHTS
		irradiance *= PI; // punctual light
	#endif
	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );//irradiance *  0.31830988618 * material.diffuseColor;//这里*0.318什么操作
	reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
}

void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );

}
#define RE_Direct				RE_Direct_BlinnPhong
#define RE_IndirectDiffuse		RE_IndirectDiffuse_BlinnPhong
#define Material_LightProbeLOD( material )	(0)

void main() {

vec4 diffuseColor = vec4( diffuse, opacity );
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0), vec3( 0.0 ) );
vec3 totalEmissiveRadiance = emissive;

#include <specularmap_fragment>

内容:高光贴图,好像事取R通道的值
float specularStrength;
#ifdef USE_SPECULARMAP
vec4 texelSpecular = texture2D( specularMap, vUv );
specularStrength = texelSpecular.r;
#else
specularStrength = 1.0;
#endif

#include <normal_fragment_begin>

内容:法向量
vec3 normal = normalize( vNormal );
vec3 geometryNormal = normal;

#include <normal_fragment_maps>

内容:法向贴图

// accumulation
#include <lights_phong_fragment>

BlinnPhongMaterial material;
material.diffuseColor = diffuseColor.rgb;
material.specularColor = specular;
material.specularShininess = shininess;
material.specularStrength = specularStrength;

#include <lights_fragment_begin>

GeometricContext geometry;
geometry.position = - vViewPosition;
geometry.normal = normal;
geometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );

IncidentLight directLight;

// 然后以平行光为例
#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )
	DirectionalLight directionalLight;
	#pragma unroll_loop_start
	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
		directionalLight = directionalLights[ i ];
		getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );
		RE_Direct( directLight, geometry, material, reflectedLight );
	}
	#pragma unroll_loop_end
#endif



//全篇最重要的:
RE_Direct执行的是上文中提到的RE_Direct_BlinnPhong,其中直接漫反射计算:
BRDF_Diffuse_Lambert


直接高光计算:
vec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {
	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
	//float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );
	//float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
	float dotNH = saturate( dot( geometry.normal, halfDir ) );
	float dotLH = saturate( dot( incidentLight.direction, halfDir ) );
	vec3 F = F_Schlick( specularColor, dotLH );
	float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );
	float D = D_BlinnPhong( shininess, dotNH );
	return F * ( G * D );
}



这里就是blinnPhong和PBR的区别,PBR这里GD计算方式有区别

这里
geometry.viewDir  是顶点到世界坐标原点000方向的单位向量 就是视线方向,整体是在世界坐标系中,这里three中视线原点我认为就是世界坐标系的原点
geometry.normal 是顶点的单位法向量
halfDir  是半角向量,视线向量和光线向量的中间值
incidentLight.direction 光线方向向量,就是顶点到光源方向的向量


billn phong BRDF 标准的布林冯模型
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 );

}

可以对比看下GGX BRDF

float G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {

	float a2 = pow2( alpha );

	// dotNL and dotNV are explicitly swapped. This is not a mistake.
	float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );
	float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );

	return 0.5 / max( gv + gl, EPSILON );

}

float D_GGX( const in float alpha, const in float dotNH ) {

	float a2 = pow2( alpha );

	float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1

	return RECIPROCAL_PI * a2 / pow2( denom );

}

#include <lights_fragment_maps>

主要是RE_IndirectDiffuse和RE_IndirectSpecular 间接漫反射和高光

#include <lights_fragment_end>

主要是RE_IndirectDiffuse和RE_IndirectSpecular 间接漫反射和高光

vec3 outgoingLight = reflectedLight.directDiffuse +
reflectedLight.indirectDiffuse + reflectedLight.directSpecular +
reflectedLight.indirectSpecular + totalEmissiveRadiance; gl_FragColor
= vec4( outgoingLight, diffuseColor.a );

综合输出直接间接漫反射、直接间接高光

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值