像素着色器(meshphysical_frag.glsl)

#define PHYSICAL

uniform vec3 diffuse; // 漫反射颜色

uniform vec3 emissive; // 自发光颜色

uniform float roughness; // 粗糙度

uniform float metalness; // 金属性

uniform float opacity;  // 透明度

#ifndef STANDARD

uniform float clearCoat;  //

uniform float clearCoatRoughness;

#endif

varying vec3 vViewPosition; // 摄像机空间的坐标

#ifndef FLAT_SHADED

varying vec3 vNormal; // 摄像机空间的法线

#endif

#include <common>           //  包含着色器公共模块(包含常用的数学工具函数以及一些常量定义什么的)

#include <packing>          // 数据编码解码功能函数

#include <dithering_pars_fragment>  // 抖动处理的定义

#include <color_pars_fragment>      // 颜色处理的定义

#include <uv_pars_fragment>         // uv相关处理的定义

#include <uv2_pars_fragment>        // uv2相关处理的定义

#include <map_pars_fragment>        // map贴图相关处理的定义

#include <alphamap_pars_fragment>   // alphamap贴图的处理定义

#include <aomap_pars_fragment>      // aomap贴图的处理定义

#include <lightmap_pars_fragment>   // lighmap贴图处理定义

#include <emissivemap_pars_fragment>    // emissivemap贴图处理的定义

#include <envmap_pars_fragment> // envmap贴图处理的定义

#include <fog_pars_fragment>    // 雾化需要的定义

#include <bsdfs>                    // brdf相关的功能函数

#include <cube_uv_reflection_fragment>  // cubemap反射相关

#include <lights_pars_begin>        // 灯光相关定义

#include <lights_pars_maps>         // 灯光贴图相关

#include <lights_physical_pars_fragment> // 灯光相关物理运算

#include <shadowmap_pars_fragment>  // shadowmap影子相关运算定义

#include <bumpmap_pars_fragment>        // bumpmap相关运算的定义

#include <normalmap_pars_fragment>      // normalmap相关运算的定义

#include <roughnessmap_pars_fragment>       // roughnessmap相关运算的定义

#include <metalnessmap_pars_fragment>       // metalnessmap相关运算的定义

#include <logdepthbuf_pars_fragment>        // logdepth相关运算的定义

#include <clipping_planes_pars_fragment>        // clipplane裁剪平面相关的定义

void main() {

#include <clipping_planes_fragment> // 裁剪平面裁剪

vec4 diffuseColor = vec4( diffuse, opacity );// 合成rgba四通道漫反射颜色

ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );

vec3 totalEmissiveRadiance = emissive;

#include <logdepthbuf_fragment> // logdepth运算

#include <map_fragment>         // map通道颜色采样

#include <color_fragment>       // color参与计算

#include <alphamap_fragment>    // alphamap通道颜色采样

#include <alphatest_fragment>   // alpha测试

#include <roughnessmap_fragment>    // 粗糙贴图采样

#include <metalnessmap_fragment>    // 金属性贴图采样

#include <normal_fragment_begin>    // 法线贴图基本运算

#include <normal_fragment_maps>     // 法线通过法线贴图运算

#include <emissivemap_fragment>     // 自发光贴图采样

// accumulation

#include <lights_physical_fragment> // 物理光照基础运算

#include <lights_fragment_begin> // 计算各种灯光入射光和反射光信息

#include <lights_fragment_maps> // 从环境光和光照贴图获取辐射

#include <lights_fragment_end>  // 根据辐射光取得反射信息

// modulation

#include <aomap_fragment>   // 根据AO贴图调整反射光照强度

// 反射光直接漫反射+间接漫反射+直接高光+间接高光+自发光 = 输出光照颜色

vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;

gl_FragColor = vec4( outgoingLight, diffuseColor.a );

#include <tonemapping_fragment>// tonemap进行曝光

#include <encodings_fragment> // 颜色编码

#include <fog_fragment>             // 雾化颜色运算

#include <premultiplied_alpha_fragment> // 颜色预乘alpha

#include <dithering_fragment>   // 颜色随机抖动

}

我将这个fragmentshader提取了关于物理材质着色的核心算法方便理解代码如下:

核心算法只包含直接照明产生的漫反射颜色和高光颜色,直接照明只计算了点光源(没有计算距离衰减),去掉了各种贴图采样数据以最简化shader代码

// 由vertexshader传递过来的法线,位置,uv
varying vec3 vNormal;
varying vec3 vPosition;
varying vec2 vUv; // 材质参数
uniform vec3 diffuse; // 漫反射
uniform float metallic; // 金属性
uniform float roughness; // 粗糙度 #if NUM_POINT_LIGHTS > 0
// 点光源信息
struct PointLight {
vec3 position;
vec3 color;
float distance;
float decay;
};
uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
#endif
#if NUM_DIR_LIGHTS > 0
struct DirectionalLight {
vec3 direction;
vec3 color;
};
uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
#endif
float pow2( const in float x ) { return x*x; }
const float PI = 3.14159265359;
#define EPSILON 1e-6
#define MAXIMUM_SPECULAR_COEFFICIENT 0.16
#define DEFAULT_SPECULAR_COEFFICIENT 0.04
#define RECIPROCAL_PI 0.31830988618
// 光照反射信息(直接光的漫反射和高光色)
struct ReflectedLight {
vec3 directDiffuse;
vec3 directSpecular;
vec3 indirectDiffuse;
};
// 入射光照信息(颜色和方向)
struct IncidentLight {
vec3 color;
vec3 direction;
};
// 几何信息(位置,法线,视角方向)
struct GeometricContext {
vec3 position;
vec3 normal;
vec3 viewDir;
};
// 物理材质信息
struct PhysicalMaterial {
vec3 diffuseColor;
float specularRoughness;
vec3 specularColor;
}; vec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {
float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );
return ( 1.0 - specularColor ) * fresnel + specularColor;
}
float G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {
float a2 = pow2( alpha );
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;
return RECIPROCAL_PI * a2 / pow2( denom );
}
vec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {
float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
const vec4 c0 = vec4( - , - 0.0275, - 0.572, 0.022 );
const vec4 c1 = vec4( , 0.0425, 1.04, - 0.04 );
vec4 r = roughness * c0 + c1;
float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
return specularColor * AB.x + AB.y;
}
vec3 BRDF_Specular_GGX( in GeometricContext geometry, in IncidentLight directLight,const in vec3 specularColor, const in float roughness) {
float alpha = pow2( roughness );
vec3 halfDir = normalize( directLight.direction + geometry.viewDir );
float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
float dotNH = saturate( dot( geometry.normal, halfDir ) );
float dotLH = saturate( dot( directLight.direction, halfDir ) );
vec3 F = F_Schlick( specularColor, dotLH );
float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );
float D = D_GGX( alpha, dotNH );
return F * ( G * D );
}
vec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {
return RECIPROCAL_PI * diffuseColor;
}
float clearCoatDHRApprox( const in float roughness, const in float dotNL ) {
return DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );
}
void RE_Direct_Physical(in GeometricContext geometry,in PhysicalMaterial material, in IncidentLight directLight,inout ReflectedLight reflectedLight ) { float dotNL = saturate( dot( geometry.normal,directLight.direction ) );// lambert漫反射因子
vec3 irradiance = dotNL * directLight.color; // 辐射
irradiance *= PI; // * PI reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
// 重点就是这里了,高光算法和blinn-phong差距巨大
reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX( geometry,directLight,material.specularColor,material.specularRoughness); }
void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
}
vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
vec3 irradiance = ambientLightColor;
irradiance *= PI;
return irradiance;
}
#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical
void main() {
// 存放几何数据
GeometricContext geometry;
geometry.position = vPosition;
geometry.normal = normalize(vNormal);
geometry.viewDir = normalize(-vPosition); // 因为是相机空间只需要对位置坐标取反0-vPosition
// 存放物理材质信息
PhysicalMaterial material;
material.diffuseColor = diffuse * ( 1.0 - metallic ); // 金属性越强漫反射颜色越小
material.specularRoughness = clamp( roughness, 0.04, 1.0 ); // 粗燥度
material.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuse.rgb, metallic ); // 这里做了个mix 金属性为0高光颜色也不至于是黑色 // 初始化光照反射
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ),vec3(0.0) ); IncidentLight directLight;// 直接入射光照
#if NUM_POINT_LIGHTS > 0
for(int i = ; i < NUM_POINT_LIGHTS; ++i)
{
directLight.color = pointLights[i].color; // 入射光颜色
directLight.direction = normalize(pointLights[i].position - vPosition); // 入射光的方向
RE_Direct_Physical(geometry,material,directLight,reflectedLight); // 计算直接光产生的反射光信息
}
#endif
#if NUM_DIR_LIGHTS > 0
for(int i = ; i < NUM_DIR_LIGHTS; ++i)
{
directLight.color = directionalLights[i].color; // 入射光颜色
directLight.direction = directionalLights[i].direction;
RE_Direct_Physical(geometry,material,directLight,reflectedLight); // 计算直接光产生的反射光信息
}
#endif vec3 irradiance = getAmbientLightIrradiance( vec3(0.13) );
RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );
// 反射光信息加合为最后颜色
vec3 color = reflectedLight.directDiffuse + reflectedLight.directSpecular+reflectedLight.indirectDiffuse; // HDR tonemapping
color = saturate(color/(color+vec3(1.0)));
// gamma correct
color = pow(color, vec3(1.0/2.0)); gl_FragColor = vec4(color, 1.0);
}

下面是一个点光源和一个方向光的效果(从左到右粗糙度加强,从下到上金属性加强):

 

 

ThreeJS 物理材质shader源码分析(像素着色器)的更多相关文章

  1. ThreeJS 物理材质shader源码分析(顶点着色器)

    再此之前推荐一款GLTF物理材质在线编辑器https://tinygltf.xyz/ ThreeJS 物理材质shader源码分析(顶点着色器) Threejs将shader代码分为ShaderLib ...

  2. springMVC源码分析--HandlerInterceptor拦截器调用过程(二)

    在上一篇博客springMVC源码分析--HandlerInterceptor拦截器(一)中我们介绍了HandlerInterceptor拦截器相关的内容,了解到了HandlerInterceptor ...

  3. WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码

    原文:WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码 HLSL,High Level Shader Language,高级着色器语言,是 Di ...

  4. springMVC源码分析之拦截器

    一个东西用久了,自然就会从仅使用的层面上升到探究其原理的层面,在javaweb中springmvc更是如此,越是优秀的框架,其底层实现代码更是复杂,而在我看来,一个优秀程序猿就相当于一名武林高手,不断 ...

  5. springMVC源码分析--HandlerInterceptor拦截器(一)

    对SpringMVC有所了解的人肯定接触过HandlerInterceptor拦截器,HandlerInterceptor接口给我们提供了3个方法: (1)preHandle: 在执行controll ...

  6. JVM源码分析--ClassLoader类加载器

    本人原创,转载请注明出处:https://www.cnblogs.com/javallh/p/10224187.html 1.JDK已有类加载器: BootStrap ClassLoader (启动类 ...

  7. AirTest源码分析之运行器

    from: https://blog.csdn.net/u012897401/article/details/82900562 使用:根据airtest文档说明,可以通过命令行来启动air脚本,需要传 ...

  8. java8学习之Collector源码分析与收集器核心

    之前已经对流在使用上已经进行了大量应用了,也就是说对于它的应用是比较熟悉了,但是比较欠缺的是对于它底层的实现还不太了解,所以接下来准备大量通过阅读官方的javadoc反过来加深对咱们已经掌握这些知识更 ...

  9. Spark源码分析之分区器的作用

    最近因为手抖,在Spark中给自己挖了一个数据倾斜的坑.为了解决这个问题,顺便研究了下Spark分区器的原理,趁着周末加班总结一下~ 先说说数据倾斜 数据倾斜是指Spark中的RDD在计算的时候,每个 ...

随机推荐

  1. 多线程之美7一ReentrantReadWriteLock源码分析

    目录 前言 在多线程环境下,为了保证线程安全, 我们通常会对共享资源加锁操作,我们常用Synchronized关键字或者ReentrantLock 来实现,这两者加锁方式都是排他锁,即同一时刻最多允许 ...

  2. 宣布一件事,通过写博客,挣到了人生的第一个 10w

    今天是 2019 年的最后一天,对于我来说,2019 年可以说是我高考进入大学以来,最重要的一年了.这一年,也是我收获最多的一年,其中最重要的收获应该就是『找工作』和『运营公众号』以及『挣到了人生的第 ...

  3. QT信号和槽函数学习笔记

    //connect 函数有4个参数 分别是 发送者 信号.接受者 ,槽 //connect(sender,signal,receiver,slot) /* * 信号和槽 * 信号 就是一个普通的函数 ...

  4. $Poj1934\ Trip$ 线性$DP+$搜索

    Luogu Description 爱丽丝和鲍伯想去度假,他们每个人都制定了一个参观城市的清单,该地区正好有26个城市,因此它们被编码为小写字母“a”到“z”.清单上可能重复出现某个城市.因为他们想一 ...

  5. .Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享

    前言:虽说公司app后端使用的是.net core+Redis+docker+k8s部署的,但是微信公众号后端使用的是IIS部署的,虽说公众号并发量不大,但领导还是使用了负载均衡,所以在介绍docke ...

  6. 探究Dubbo的拓展机制: 上

    这篇博文是我决心深度学习Dubbo框架时记录的笔记, 主题是Dubbo的拓展点, 下面的几个部分相对来说比较零散, 貌似是不和主题挂钩的 , 并且是一些很冷门的知识点 , 但是它们确实是深入学习Dub ...

  7. Java添加、读取Excel公式

    操作excel表格用公式来处理数据时,可通过创建公式来运算数据,或通过读取公式来获取数据信息来源.本文以通过Java代码来演示在Excel中创建及读取公式的方法.这里使用了Excel Java类库(F ...

  8. Winform PPT切换图片效果

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. EntityFramework Core一劳永逸动态加载模型,我们要知道些什么呢?

    前言 这篇文章源于一位问我的童鞋:在EntityFramework Core中如何动态加载模型呢?在学习EntityFramwork时关于这个问题已有对应园友给出答案,故没有过多研究,虽然最后解决了这 ...

  10. 【Javaweb学习笔记】XML和约束模式

    一.XML语法 xml 可扩展标记语言,w3c组织发布的,用于保存有关系的数据,作为配置文件,描述程序模块之间的关系 xml 文件开头必须包括下面的标签: <?xml version=" ...