VSG示例中的PBR
链接:
vsgshaderset示例¶
命令行参数说明
-i
输入的模型--pbr
源码阅读¶
standard.vert¶
#version 450
#extension GL_ARB_separate_shader_objects : enable
#pragma import_defines (VSG_INSTANCE_POSITIONS, VSG_DISPLACEMENT_MAP)
layout(push_constant) uniform PushConstants {
mat4 projection;
mat4 modelView;
} pc;
#ifdef VSG_DISPLACEMENT_MAP
layout(binding = 6) uniform sampler2D displacementMap;
#endif
layout(location = 0) in vec3 vsg_Vertex; //顶点位置(模型坐标系)
layout(location = 1) in vec3 vsg_Normal; //顶点法向量(模型坐标系)
layout(location = 2) in vec2 vsg_TexCoord0; //顶点UV
layout(location = 3) in vec4 vsg_Color; //顶点颜色
#ifdef VSG_INSTANCE_POSITIONS
layout(location = 4) in vec3 vsg_position; //中心点(模型坐标系原点的偏移值)
#endif
layout(location = 0) out vec3 eyePos; //顶点位置(相机坐标系)
layout(location = 1) out vec3 normalDir; //法向量(相机坐标系)
layout(location = 2) out vec4 vertexColor; //顶点颜色
layout(location = 3) out vec2 texCoord0; //UV
layout(location = 5) out vec3 viewDir; //视线方向,指向摄像机(相机坐标系)
out gl_PerVertex{ vec4 gl_Position; };
void main()
{
vec4 vertex = vec4(vsg_Vertex, 1.0);
vec4 normal = vec4(vsg_Normal, 0.0);
#ifdef VSG_DISPLACEMENT_MAP
// TODO need to pass as as uniform or per instance attributes
vec3 scale = vec3(1.0, 1.0, 1.0);
vertex.xyz = vertex.xyz + vsg_Normal * (texture(displacementMap, vsg_TexCoord0.st).s * scale.z);
float s_delta = 0.01;
float width = 0.0;
float s_left = max(vsg_TexCoord0.s - s_delta, 0.0);
float s_right = min(vsg_TexCoord0.s + s_delta, 1.0);
float t_center = vsg_TexCoord0.t;
float delta_left_right = (s_right - s_left) * scale.x;
float dz_left_right = (texture(displacementMap, vec2(s_right, t_center)).s - texture(displacementMap, vec2(s_left, t_center)).s) * scale.z;
// TODO need to handle different origins of displacementMap vs diffuseMap etc,
float t_delta = s_delta;
float t_bottom = max(vsg_TexCoord0.t - t_delta, 0.0);
float t_top = min(vsg_TexCoord0.t + t_delta, 1.0);
float s_center = vsg_TexCoord0.s;
float delta_bottom_top = (t_top - t_bottom) * scale.y;
float dz_bottom_top = (texture(displacementMap, vec2(s_center, t_top)).s - texture(displacementMap, vec2(s_center, t_bottom)).s) * scale.z;
vec3 dx = normalize(vec3(delta_left_right, 0.0, dz_left_right));
vec3 dy = normalize(vec3(0.0, delta_bottom_top, -dz_bottom_top));
vec3 dz = normalize(cross(dx, dy));
normal.xyz = normalize(dx * vsg_Normal.x + dy * vsg_Normal.y + dz * vsg_Normal.z);
#endif
#ifdef VSG_INSTANCE_POSITIONS
vertex.xyz = vertex.xyz + vsg_position; //加上中心点
#endif
gl_Position = (pc.projection * pc.modelView) * vertex; //顶点位置(标准化设备坐标)
eyePos = (pc.modelView * vertex).xyz; //顶点位置(相机坐标系)
vec4 lpos = /*vsg_LightSource.position*/ vec4(0.0, 0.0, 1.0, 0.0);
viewDir = - (pc.modelView * vertex).xyz; //0(相机坐标系,即相机所在位置)-顶点位置(相机坐标系) = 视线方向,指向摄像机
normalDir = (pc.modelView * normal).xyz; //法向量
//注意:modelView是4x4,其中包含平移量。而法向量只是向量,不需要做平移,只需要做旋转与缩放等变换
// 因此乘完以后取xyz即可
//或者这么写:normalDir = mat3(pc.modelView) * normal;
vertexColor = vsg_Color;
texCoord0 = vsg_TexCoord0;
}
standard_pbr.frag¶
#version 450
#extension GL_ARB_separate_shader_objects : enable
#pragma import_defines (VSG_DIFFUSE_MAP, VSG_GREYSACLE_DIFFUSE_MAP, VSG_EMISSIVE_MAP, VSG_LIGHTMAP_MAP, VSG_NORMAL_MAP, VSG_METALLROUGHNESS_MAP, VSG_SPECULAR_MAP, VSG_TWO_SIDED_LIGHTING, VSG_WORKFLOW_SPECGLOSS)
const float PI = 3.14159265359;
const float RECIPROCAL_PI = 0.31830988618; //PI的倒数
const float RECIPROCAL_PI2 = 0.15915494;
const float EPSILON = 1e-6;
const float c_MinRoughness = 0.04; //最小的粗糙度
//漫反射贴图
#ifdef VSG_DIFFUSE_MAP
layout(binding = 0) uniform sampler2D diffuseMap;
#endif
//金属度贴图
#ifdef VSG_METALLROUGHNESS_MAP
layout(binding = 1) uniform sampler2D mrMap;
#endif
//法向量贴图
#ifdef VSG_NORMAL_MAP
layout(binding = 2) uniform sampler2D normalMap;
#endif
//环境光吸收贴图
#ifdef VSG_LIGHTMAP_MAP
layout(binding = 3) uniform sampler2D aoMap;
#endif
//自发光贴图
#ifdef VSG_EMISSIVE_MAP
layout(binding = 4) uniform sampler2D emissiveMap;
#endif
//镜面反射贴图
#ifdef VSG_SPECULAR_MAP
layout(binding = 5) uniform sampler2D specularMap;
#endif
layout(binding = 10) uniform PbrData
{
vec4 baseColorFactor; //基础颜色因子
vec4 emissiveFactor; //自发光因子
vec4 diffuseFactor; //漫反射因子
vec4 specularFactor; //镜面反射因子
float metallicFactor; //金属因子
float roughnessFactor; //粗糙度因子
float alphaMask;
float alphaMaskCutoff;
} pbr;
/* 光源数据
values[0]
第一个vec4存储每种灯光的个数,一共有4中
分别是:环境光、方向光、点光源、聚光灯
values[1:64]连续存储具体的灯光,根据灯光数量以此存储
每种光源存储的信息量也不同,具体如下:
环境光:光的能量
方向光:光的能量、光的方向
点光源:光的能量、光的位置
聚光灯:光的能量、position_cosInnerAngle、lightDirection_cosOuterAngle
*/
layout(set = 1, binding = 0) uniform LightData
{
vec4 values[64];
} lightData;
layout(location = 0) in vec3 eyePos; //顶点位置(相机坐标系)
layout(location = 1) in vec3 normalDir; //法向量(相机坐标系)
layout(location = 2) in vec4 vertexColor; //顶点颜色
layout(location = 3) in vec2 texCoord0; //UV
layout(location = 5) in vec3 viewDir; //视线方向,指向摄像机(相机坐标系)
layout(location = 0) out vec4 outColor;
// Encapsulate the various inputs used by the various functions in the shading equation
// We store values in this struct to simplify the integration of alternative implementations
// of the shading terms, outlined in the Readme.MD Appendix.
struct PBRInfo
{
float NdotL; // cos angle between normal and light direction
float NdotV; // cos angle between normal and view direction
float NdotH; // cos angle between normal and half vector
float LdotH; // cos angle between light direction and half vector
float VdotH; // cos angle between view direction and half vector
float VdotL; // cos angle between view direction and light direction
float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
float metalness; // metallic value at the surface
vec3 reflectance0; // full reflectance color (normal incidence angle)
vec3 reflectance90; // reflectance color at grazing angle
float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
vec3 diffuseColor; // color contribution from diffuse lighting
vec3 specularColor; // color contribution from specular lighting
};
vec4 SRGBtoLINEAR(vec4 srgbIn)
{
vec3 linOut = pow(srgbIn.xyz, vec3(2.2));
return vec4(linOut,srgbIn.w);
}
vec4 LINEARtoSRGB(vec4 srgbIn)
{
vec3 linOut = pow(srgbIn.xyz, vec3(1.0 / 2.2));
return vec4(linOut, srgbIn.w);
}
float rcp(const in float value)
{
return 1.0 / value;
}
float pow5(const in float value)
{
return value * value * value * value * value;
}
// Find the normal for this fragment, pulling either from a predefined normal map
// or from the interpolated mesh normal and tangent attributes.
vec3 getNormal()
{
#ifdef VSG_NORMAL_MAP
// Perturb normal, see http://www.thetenthplanet.de/archives/1180
vec3 tangentNormal = texture(normalMap, texCoord0).xyz * 2.0 - 1.0;
//tangentNormal *= vec3(2,2,1);
vec3 q1 = dFdx(eyePos);
vec3 q2 = dFdy(eyePos);
vec2 st1 = dFdx(texCoord0);
vec2 st2 = dFdy(texCoord0);
vec3 N = normalize(normalDir);
vec3 T = normalize(q1 * st2.t - q2 * st1.t);
vec3 B = -normalize(cross(N, T));
mat3 TBN = mat3(T, B, N);
return normalize(TBN * tangentNormal);
#else
return normalize(normalDir);
#endif
}
// Basic Lambertian diffuse
// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
// See also [1], Equation 1
vec3 BRDF_Diffuse_Lambert(PBRInfo pbrInputs)
{
return pbrInputs.diffuseColor * RECIPROCAL_PI;
}
vec3 BRDF_Diffuse_Custom_Lambert(PBRInfo pbrInputs)
{
return pbrInputs.diffuseColor * RECIPROCAL_PI * pow(pbrInputs.NdotV, 0.5 + 0.3 * pbrInputs.perceptualRoughness);
}
// [Gotanda 2012, "Beyond a Simple Physically Based Blinn-Phong Model in Real-Time"]
vec3 BRDF_Diffuse_OrenNayar(PBRInfo pbrInputs)
{
float a = pbrInputs.alphaRoughness;
float s = a;// / ( 1.29 + 0.5 * a );
float s2 = s * s;
float VoL = 2 * pbrInputs.VdotH * pbrInputs.VdotH - 1; // double angle identity
float Cosri = pbrInputs.VdotL - pbrInputs.NdotV * pbrInputs.NdotL;
float C1 = 1 - 0.5 * s2 / (s2 + 0.33);
float C2 = 0.45 * s2 / (s2 + 0.09) * Cosri * ( Cosri >= 0 ? 1.0 / max(pbrInputs.NdotL, pbrInputs.NdotV) : 1 );
return pbrInputs.diffuseColor / PI * ( C1 + C2 ) * ( 1 + pbrInputs.perceptualRoughness * 0.5 );
}
// [Gotanda 2014, "Designing Reflectance Models for New Consoles"]
vec3 BRDF_Diffuse_Gotanda(PBRInfo pbrInputs)
{
float a = pbrInputs.alphaRoughness;
float a2 = a * a;
float F0 = 0.04;
float VoL = 2 * pbrInputs.VdotH * pbrInputs.VdotH - 1; // double angle identity
float Cosri = VoL - pbrInputs.NdotV * pbrInputs.NdotL;
float a2_13 = a2 + 1.36053;
float Fr = ( 1 - ( 0.542026*a2 + 0.303573*a ) / a2_13 ) * ( 1 - pow( 1 - pbrInputs.NdotV, 5 - 4*a2 ) / a2_13 ) * ( ( -0.733996*a2*a + 1.50912*a2 - 1.16402*a ) * pow( 1 - pbrInputs.NdotV, 1 + rcp(39*a2*a2+1) ) + 1 );
//float Fr = ( 1 - 0.36 * a ) * ( 1 - pow( 1 - NoV, 5 - 4*a2 ) / a2_13 ) * ( -2.5 * Roughness * ( 1 - NoV ) + 1 );
float Lm = ( max( 1 - 2*a, 0 ) * ( 1 - pow5( 1 - pbrInputs.NdotL ) ) + min( 2*a, 1 ) ) * ( 1 - 0.5*a * (pbrInputs.NdotL - 1) ) * pbrInputs.NdotL;
float Vd = ( a2 / ( (a2 + 0.09) * (1.31072 + 0.995584 * pbrInputs.NdotV) ) ) * ( 1 - pow( 1 - pbrInputs.NdotL, ( 1 - 0.3726732 * pbrInputs.NdotV * pbrInputs.NdotV ) / ( 0.188566 + 0.38841 * pbrInputs.NdotV ) ) );
float Bp = Cosri < 0 ? 1.4 * pbrInputs.NdotV * pbrInputs.NdotL * Cosri : Cosri;
float Lr = (21.0 / 20.0) * (1 - F0) * ( Fr * Lm + Vd + Bp );
return pbrInputs.diffuseColor * RECIPROCAL_PI * Lr;
}
vec3 BRDF_Diffuse_Burley(PBRInfo pbrInputs)
{
float energyBias = mix(pbrInputs.perceptualRoughness, 0.0, 0.5);
float energyFactor = mix(pbrInputs.perceptualRoughness, 1.0, 1.0 / 1.51);
float fd90 = energyBias + 2.0 * pbrInputs.VdotH * pbrInputs.VdotH * pbrInputs.perceptualRoughness;
float f0 = 1.0;
float lightScatter = f0 + (fd90 - f0) * pow(1.0 - pbrInputs.NdotL, 5.0);
float viewScatter = f0 + (fd90 - f0) * pow(1.0 - pbrInputs.NdotV, 5.0);
return pbrInputs.diffuseColor * lightScatter * viewScatter * energyFactor;
}
vec3 BRDF_Diffuse_Disney(PBRInfo pbrInputs)
{
float Fd90 = 0.5 + 2.0 * pbrInputs.perceptualRoughness * pbrInputs.VdotH * pbrInputs.VdotH;
vec3 f0 = vec3(0.1);
vec3 invF0 = vec3(1.0, 1.0, 1.0) - f0;
float dim = min(invF0.r, min(invF0.g, invF0.b));
float result = ((1.0 + (Fd90 - 1.0) * pow(1.0 - pbrInputs.NdotL, 5.0 )) * (1.0 + (Fd90 - 1.0) * pow(1.0 - pbrInputs.NdotV, 5.0 ))) * dim;
return pbrInputs.diffuseColor * result;
}
// The following equation models the Fresnel reflectance term of the spec equation (aka F())
// Implementation of fresnel from [4], Equation 15
vec3 specularReflection(PBRInfo pbrInputs)
{
//return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance90*pbrInputs.reflectance0) * exp2((-5.55473 * pbrInputs.VdotH - 6.98316) * pbrInputs.VdotH);
}
// This calculates the specular geometric attenuation (aka G()),
// where rougher material will reflect less light back to the viewer.
// This implementation is based on [1] Equation 4, and we adopt their modifications to
// alphaRoughness as input as originally proposed in [2].
float geometricOcclusion(PBRInfo pbrInputs)
{
float NdotL = pbrInputs.NdotL;
float NdotV = pbrInputs.NdotV;
float r = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r + (1.0 - r) * (NdotL * NdotL)));
float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r + (1.0 - r) * (NdotV * NdotV)));
return attenuationL * attenuationV;
}
// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D())
// Implementation from "Average Irregularity Representation of a Roughened Surface for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3.
float microfacetDistribution(PBRInfo pbrInputs)
{
float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
return roughnessSq / (PI * f * f);
}
/*BRDF
*/
vec3 BRDF(vec3 u_LightColor, vec3 v, vec3 n, vec3 l, vec3 h, float perceptualRoughness, float metallic, vec3 specularEnvironmentR0, vec3 specularEnvironmentR90, float alphaRoughness, vec3 diffuseColor, vec3 specularColor, float ao)
{
float unclmapped_NdotL = dot(n, l);
#ifdef VSG_TWO_SIDED_LIGHTING
if (unclmapped_NdotL < 0.0)
{
n = -n;
unclmapped_NdotL = -unclmapped_NdotL;
}
#endif
vec3 reflection = -normalize(reflect(v, n));
reflection.y *= -1.0f;
float NdotL = clamp(unclmapped_NdotL, 0.001, 1.0);
float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
float NdotH = clamp(dot(n, h), 0.0, 1.0);
float LdotH = clamp(dot(l, h), 0.0, 1.0);
float VdotH = clamp(dot(v, h), 0.0, 1.0);
float VdotL = clamp(dot(v, l), 0.0, 1.0);
PBRInfo pbrInputs = PBRInfo(NdotL,
NdotV,
NdotH,
LdotH,
VdotH,
VdotL,
perceptualRoughness,
metallic,
specularEnvironmentR0,
specularEnvironmentR90,
alphaRoughness,
diffuseColor,
specularColor);
// Calculate the shading terms for the microfacet specular shading model
vec3 F = specularReflection(pbrInputs); //菲涅尔函数
float G = geometricOcclusion(pbrInputs); //几何函数
float D = microfacetDistribution(pbrInputs); //法线方程
// Calculation of analytical lighting contribution
vec3 diffuseContrib = (1.0 - F) * BRDF_Diffuse_Disney(pbrInputs); //漫反射项
vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); //镜面反射项
// Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib);
color *= ao;
#ifdef VSG_EMISSIVE_MAP
vec3 emissive = SRGBtoLINEAR(texture(emissiveMap, texCoord0)).rgb * pbr.emissiveFactor.rgb;
#else
vec3 emissive = pbr.emissiveFactor.rgb;
#endif
color += emissive;
return color;
}
float convertMetallic(vec3 diffuse, vec3 specular, float maxSpecular)
{
float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b);
float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b);
if (perceivedSpecular < c_MinRoughness)
{
return 0.0;
}
float a = c_MinRoughness;
float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness;
float c = c_MinRoughness - perceivedSpecular;
float D = max(b * b - 4.0 * a * c, 0.0);
return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
}
void main()
{
float perceptualRoughness = 0.0;
float metallic;
vec3 diffuseColor;
vec4 baseColor;
float ambientOcclusion = 1.0;
vec3 f0 = vec3(0.04);
#ifdef VSG_DIFFUSE_MAP
#ifdef VSG_GREYSACLE_DIFFUSE_MAP
float v = texture(diffuseMap, texCoord0.st).s * pbr.baseColorFactor;
baseColor = vertexColor * vec4(v, v, v, 1.0);
#else
baseColor = vertexColor * SRGBtoLINEAR(texture(diffuseMap, texCoord0)) * pbr.baseColorFactor;
#endif
#else
baseColor = vertexColor * pbr.baseColorFactor;
#endif
if (pbr.alphaMask == 1.0f)
{
if (baseColor.a < pbr.alphaMaskCutoff)
discard;
}
#ifdef VSG_WORKFLOW_SPECGLOSS
#ifdef VSG_DIFFUSE_MAP
vec4 diffuse = SRGBtoLINEAR(texture(diffuseMap, texCoord0));
#else
vec4 diffuse = vec4(1.0);
#endif
#ifdef VSG_SPECULAR_MAP
vec3 specular = SRGBtoLINEAR(texture(specularMap, texCoord0)).rgb;
perceptualRoughness = 1.0 - texture(specularMap, texCoord0).a;
#else
vec3 specular = vec3(0.0);
perceptualRoughness = 0.0;
#endif
float maxSpecular = max(max(specular.r, specular.g), specular.b);
// Convert metallic value from specular glossiness inputs
metallic = convertMetallic(diffuse.rgb, specular, maxSpecular);
const float epsilon = 1e-6;
vec3 baseColorDiffusePart = diffuse.rgb * ((1.0 - maxSpecular) / (1 - c_MinRoughness) / max(1 - metallic, epsilon)) * pbr.diffuseFactor.rgb;
vec3 baseColorSpecularPart = specular - (vec3(c_MinRoughness) * (1 - metallic) * (1 / max(metallic, epsilon))) * pbr.specularFactor.rgb;
baseColor = vec4(mix(baseColorDiffusePart, baseColorSpecularPart, metallic * metallic), diffuse.a);
#else
perceptualRoughness = pbr.roughnessFactor;
metallic = pbr.metallicFactor;
#ifdef VSG_METALLROUGHNESS_MAP
vec4 mrSample = texture(mrMap, texCoord0);
perceptualRoughness = mrSample.g * perceptualRoughness;
metallic = mrSample.b * metallic;
#endif
#endif
#ifdef VSG_LIGHTMAP_MAP
ambientOcclusion = texture(aoMap, texCoord0).r;
#endif
diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
diffuseColor *= 1.0 - metallic;
float alphaRoughness = perceptualRoughness * perceptualRoughness;
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
// Compute reflectance.
float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
// For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
// For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
vec3 specularEnvironmentR0 = specularColor.rgb;
vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
vec3 n = getNormal();
vec3 v = normalize(viewDir); // Vector from surface point to camera
float shininess = 100.0f;
vec3 color = vec3(0.0, 0.0, 0.0);
//从lightData取出灯光
vec4 lightNums = lightData.values[0]; //第一个vec4,存储着每种灯光的数量
int numAmbientLights = int(lightNums[0]); //环境光数量
int numDirectionalLights = int(lightNums[1]); //方向等数量
int numPointLights = int(lightNums[2]); //点光源数量
int numSpotLights = int(lightNums[3]); //聚光灯数量
int index = 1;
//环境光
if (numAmbientLights>0)
{
// ambient lights
for(int i = 0; i<numAmbientLights; ++i)
{
vec4 ambient_color = lightData.values[index++]; //环境光能量
color += (baseColor.rgb * ambient_color.rgb) * (ambient_color.a * ambientOcclusion);
}
}
//定向光:不会随着距离而衰减
if (numDirectionalLights>0)
{
// directional lights
for(int i = 0; i<numDirectionalLights; ++i)
{
vec4 lightColor = lightData.values[index++]; //定向光能量
vec3 direction = -lightData.values[index++].xyz; //定向光的方向
vec3 l = direction; // Vector from surface point to light
vec3 h = normalize(l+v); // Half vector between both l and v
float scale = lightColor.a;
color.rgb += BRDF(lightColor.rgb * scale, v, n, l, h, perceptualRoughness, metallic, specularEnvironmentR0, specularEnvironmentR90, alphaRoughness, diffuseColor, specularColor, ambientOcclusion);
}
}
//点光源:随着距离而衰减
if (numPointLights>0)
{
// point light
for(int i = 0; i<numPointLights; ++i)
{
vec4 lightColor = lightData.values[index++]; //点光源能量
vec3 position = lightData.values[index++].xyz; //点光源的位置
vec3 delta = position - eyePos;
float distance2 = delta.x * delta.x + delta.y * delta.y + delta.z * delta.z;
vec3 direction = delta / sqrt(distance2);
vec3 l = direction; // Vector from surface point to light
vec3 h = normalize(l+v); // Half vector between both l and v
float scale = lightColor.a / distance2;
color.rgb += BRDF(lightColor.rgb * scale, v, n, l, h, perceptualRoughness, metallic, specularEnvironmentR0, specularEnvironmentR90, alphaRoughness, diffuseColor, specularColor, ambientOcclusion);
}
}
//聚光灯:根据方向向量来缩放的
if (numSpotLights>0)
{
// spot light
for(int i = 0; i<numSpotLights; ++i)
{
vec4 lightColor = lightData.values[index++]; //聚光灯能量
vec4 position_cosInnerAngle = lightData.values[index++];
vec4 lightDirection_cosOuterAngle = lightData.values[index++];
vec3 delta = position_cosInnerAngle.xyz - eyePos;
float distance2 = delta.x * delta.x + delta.y * delta.y + delta.z * delta.z;
vec3 direction = delta / sqrt(distance2);
float dot_lightdirection = -dot(lightDirection_cosOuterAngle.xyz, direction);
vec3 l = direction; // Vector from surface point to light
vec3 h = normalize(l+v); // Half vector between both l and v
float scale = (lightColor.a * smoothstep(lightDirection_cosOuterAngle.w, position_cosInnerAngle.w, dot_lightdirection)) / distance2;
color.rgb += BRDF(lightColor.rgb * scale, v, n, l, h, perceptualRoughness, metallic, specularEnvironmentR0, specularEnvironmentR90, alphaRoughness, diffuseColor, specularColor, ambientOcclusion);
}
}
outColor = LINEARtoSRGB(vec4(color, baseColor.a));
}