首页 > 其他分享 >PBR

PBR

时间:2024-02-19 14:34:44浏览次数:21  
标签:PBR UNITY half float3 data gi giInput

简介

PBR全称Physically Based Rendering

即基于物理的渲染

它包含很多技术,折射、反射、GI、PBS等

其中的重点就是PBS

 

PBS

PBS全称Physically Based Shadering

即基于物理的着色

这是PBR的核心

而PBS的核心有

1.物质的光学特性

主要根据反射率去分为金属和非金属

金属

1.具有很高的反射率(>=0.5)

2.会立即吸收折射光,因此金属不会出现任何次表面散射或是透明效果

3.所有颜色都来自反射

非金属

1.具有很低的反射率(<=0.06)

2.会产生高光反射和漫反射

3.高光反射为单色/灰色

2.微平面理论

3.能量守恒

因此,镜面反射+漫反射<=入射光

4.菲涅尔反射

菲涅尔效应是一种表示光线的反射率与视角相关的现象

即视角观察方向于平面法线的对应关系

夹角越大,反射率就越大,亮度也就越亮

夹角越小,反射率就越小,亮度也就越低

5.线性空间光照

与之相对有个伽马空间

对于线性的颜色变化

人眼看到的

显示器输出的

可以看出他们是一样的

因此sRGB图就是在此基础上的矫正,但这会让着色器在计算时出现误差

因此需要使用Linear空间

双向反射分布函数BRDF

渲染方程

描述了光能在场景中的流动,根据光的物理学原理,渲染方程可以完美模拟出符合物理光学的结果

那个积分就是来自其他片段的漫反射

迪士尼原则的BRDF

1.使用直观的参数,而不是晦涩的物理参数

2.参数尽可能的少

3.参数在其合理范围内应该为0-1

4.允许参数在有意义的情况下超出正常范围

5.所有参数组应该尽可能的独立与合理

BaseColor固有色:表面的颜色,通常由纹理提供

SubSurface次表面:使用次表面近似的控制漫反射形状

Metallic金属度:0=非金属,1=金属,这是两种不同模型之间的线性混合

Specular镜面反射强度:字面意思

SpecularTint镜面反射颜色:对美术控制的让步,用于对BaseColor的入射镜面反射进行颜色控制

Roughness粗糙度:表面粗糙度,控制漫反射和镜面反射

Anisotropic各向异性强度:0=各项同性,1=各向异性,用于控制镜面反射高光的纵横比

Sheen光泽度:一种额外的掠射分量,主要用于布料

SheenTint光泽颜色:对Sheen的颜色控制

ClearCoat清漆强度:特殊用途的第二个镜面波瓣

ClearCoatGloss清漆光泽度:控制透明涂层光泽度

 

Shader&Cginc实现

1.准备材料

在Unity商店下载了个模型

带基础色、金属度、AO、法线、粗糙度贴图

2.创建标准表面shader,并解码,我们修改解码后的shader

1685行代码,没关系,我们进行优化

3.shader

1.属性部分

Properties
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Metallic ("Metallic", Range(0,1)) = 0.0
_MetallicTex ("MaterialTex", 2D) = "white" {}
_Smoothness ("Smoothness", Range(0,1)) = 0.5
_AO ("AO", Range(0,1)) = 1
_AOTex ("AOTex", 2D) = "white" {}
_NormalTex ("NormalTex", 2D) = "bump" {}

2.Pass部分

FORWARD
 Name "FORWARD"
Tags { "LightMode"="ForwardBase" }

CGPROGRAM

#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#pragma multi_compile_fog
#pragma multi_compile_fwdbase

#include "UnityCG.cginc"
#include "AutoLight.cginc"
    
#include "Lighting.cginc"//GI部分
#include "UnityPBSLighting.cginc"//PBS部分
//要么走下面这个,要么走上面两个
//#include "./MyPBS.cginc"//这是走自己的cginc

struct a2v
{
    float4 vertex:POSITION;
    float3 normal:NORMAL;
    float3 tangent:TANGENT;
    float2 uv:TEXCOORD0;
    float4 texcoord1:TEXCOORD1;
};

struct v2f
{
    float4 pos:SV_POSITION;
    float2 uv:TEXCOORD0;
    float3 worldNormal:TEXCOORD1;
    float3 worldPos:TEXCOORD2;
    #if UNITY_SHOULD_SAMPLE_SH
        half3 sh:TEXCOORD3;
    #endif
    UNITY_FOG_COORDS(4)
    UNITY_SHADOW_COORDS(5)
    float3 tSpace1:TEXCOORD6;
    float3 tSpace2:TEXCOORD7;
    float3 tSpace3:TEXCOORD8;
};

sampler2D _MainTex;fixed4 _MainTex_ST;
fixed4 _Color;
half _Smoothness;
half _Metallic;sampler2D _MetallicTex;
half _AO;sampler2D _AOTex;
sampler2D _NormalTex;

v2f vert(a2v v)
{
    v2f o;
    UNITY_INITIALIZE_OUTPUT(v2f,o);
    o.pos = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv,_MainTex);

    fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
    fixed3 worldTangent = UnityObjectToWorldDir(v.tangent);
    fixed3 worldBinormal = cross(worldNormal, worldTangent);
    o.tSpace1 = fixed3(worldTangent.x, worldBinormal.x, worldNormal.x);
    o.tSpace2 = fixed3(worldTangent.y, worldBinormal.y, worldNormal.y);
    o.tSpace3 = fixed3(worldTangent.z, worldBinormal.z, worldNormal.z);

    o.worldNormal = worldNormal;
    o.worldPos = mul(unity_ObjectToWorld,v.vertex);
    UNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy);
    UNITY_TRANSFER_FOG(o,o.pos);
    return o;
}

fixed4 frag(v2f i):SV_Target
{
    UNITY_EXTRACT_FOG(i);

    float3 worldPos = i.worldPos.xyz;

    float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));

    SurfaceOutputStandard o;
    UNITY_INITIALIZE_OUTPUT(SurfaceOutputStandard,o);

    o.Albedo = tex2D(_MainTex,i.uv.xy) * _Color;
    float3 norTex = UnpackNormal(tex2D(_NormalTex, i.uv));
    o.Normal = fixed3(dot(i.tSpace1,norTex),dot(i.tSpace2,norTex),dot(i.tSpace3,norTex));
    o.Emission = 0;
    o.Metallic = tex2D(_MetallicTex,i.uv).r * _Metallic;
    o.Smoothness = _Smoothness;
    o.Occlusion = tex2D(_AOTex,i.uv).r * _AO;
    o.Alpha = 1;

    UNITY_LIGHT_ATTENUATION(atten, i, worldPos);

    UnityGI gi;
    UNITY_INITIALIZE_OUTPUT(UnityGI,gi);
    gi.indirect.diffuse = 0;
    gi.indirect.specular = 0;
    gi.light.color = _LightColor0.rgb;
    gi.light.dir = _WorldSpaceLightPos0;

    UnityGIInput giInput;
    UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput);
    giInput.light = gi.light;
    giInput.worldPos = worldPos;
    giInput.worldViewDir = worldViewDir;
    giInput.atten = atten;

    #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXED
        giInput.ambient = i.sh;
    #else
        giInput.ambient = 0.0;
    #endif
    giInput.probeHDR[0] = unity_SpecCube0_HDR;
    giInput.probeHDR[1] = unity_SpecCube1_HDR;
    #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
      giInput.boxMin[0] = unity_SpecCube0_BoxMin;
    #endif

    LightingStandard_GI(o,giInput,gi);

    fixed4 c = LightingStandard(o,worldViewDir,gi);

    UNITY_APPLY_FOG(_unity_fogCoord,c);

    return c;
}

ENDCG

CGInc-GI部分

主要是对LightingStandard_GI的解析

它就是去拿了全局烘焙贴图,当做漫反射

然后再去拿反射贴图(反射探针)烘焙出来的环境光贴图,当做高光反射

GI.cginc
 #ifndef UNITY_SPECCUBE_LOD_STEPS
#define UNITY_SPECCUBE_LOD_STEPS (6)
#endif

#include "UnityLightingCommon.cginc"

//源自UnityPBSLighting.cginc
struct SurfaceOutputStandard
{
    fixed3 Albedo;
    float3 Normal;
    half3 Emission;
    half Metallic;
    half Smoothness;
    half Occlusion;
    fixed Alpha;
};

//源自...不重要
struct Unity_GlossyEnvironmentData
{
    half roughness;
    half3 reflUVW;
};

//读取高光环境贴图
half3 Unity_GlossyEnvironment(UNITY_ARGS_TEXCUBE(tex), half4 hdr, Unity_GlossyEnvironmentData glossIn)
{   
    //计算粗糙度,0-1区间是个上凸曲线
    half perceptualRoughness = glossIn.roughness;
    perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);

    //根据粗糙度去决定读取哪个mipmap,及LOD
    half mip = perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
    //反射方向
    half3 R = glossIn.reflUVW;
    //读取高光环境贴图
    half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);

    return DecodeHDR(rgbm, hdr);
}

//获取高光反射部分
half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
{
    half3 specular = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
    return specular * occlusion;
}

//获取漫反射部分
void UnityGI_Base(UnityGIInput data, half occlusion, half3 normalWorld, inout UnityGI gi)
{
    //如果有烘焙光照,就去读Baked贴图
    #if defined(LIGHTMAP_ON)
        half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
        half3 bakedColor = DecodeLightmap(bakedColorTex);

        #ifdef DIRLIGHTMAP_COMBINED
            fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER (unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);
            gi.indirect.diffuse += DecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);
        #endif
    #endif

    //将衰减应用于灯光颜色在
    gi.light.color *= data.atten;

    //环境光遮蔽
    gi.indirect.diffuse *= occlusion;
}

//获取全局光照
void UnityGlobalIllumination(SurfaceOutputStandard s, UnityGIInput data, inout UnityGI gi)
{
    //获取漫反射部分
    UnityGI_Base(data, s.Occlusion, s.Normal, gi);
    
    //获得一个粗糙度和反射方向
    Unity_GlossyEnvironmentData glossIn;
    glossIn.roughness = 1 - s.Smoothness;
    glossIn.reflUVW = reflect(-data.worldViewDir, s.Normal);
    //获取高光反射
    gi.indirect.specular = UnityGI_IndirectSpecular(data, s.Occlusion, glossIn);
}

//套一层,主要这是Unity内置方法的魔改
void LightingStandard_GI(SurfaceOutputStandard s, UnityGIInput data, inout UnityGI gi)
{
    //将数据传入
    UnityGlobalIllumination(s, data, gi);
}

 

标签:PBR,UNITY,half,float3,data,gi,giInput
From: https://www.cnblogs.com/LateUpdate/p/17974061

相关文章

  • RLHF · PbRL | 速通 ICLR 2024 RLHF
    检索关键词:ICLR2024、reinforcementlearning、preference、humanfeedback。https://openreview.net/search?term=ICLR+2024+reinforcement+learning+preference+human+feedback&group=all&content=all&source=forumContrastivePreferenceLearning:LearningfromH......
  • 基于物理的渲染(3):OSG中PBR实践
    1.1单光源直接光照voidmain(){ //创建小球几何 osg::ref_ptr<osg::ShapeDrawable>sphere=newosg::ShapeDrawable; sphere->setShape(newosg::Sphere(osg::Vec3(0,0,0),radius)); sphere->setColor(osg::Vec4(col)); //创建小球节点 osg::ref_ptr<osg::Geode>pbr......
  • PBR纹理贴图类型详解
    在线工具推荐:3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.jsAI自动纹理开发包 - YOLO虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎PBR纹理是一种帮助3D艺术家使他们的3D渲染看起来更逼真的技术。与其他着色......
  • offline RL | Pessimistic Bootstrapping (PBRL):在 Q 更新中惩罚 uncertainty,拉低 OOD
    论文题目:PessimisticBootstrappingforUncertainty-DrivenOfflineReinforcementLearning,ICLR2022,6688spotlight。pdf版本:https://arxiv.org/abs/2202.11566html版本:https://ar5iv.labs.arxiv.org/html/2202.11566openreview:https://openreview.net/forum?id=Y4c......
  • RLHF · PbRL | 选择 near on-policy query,加速 policy learning 收敛速度
    论文题目:Query-PolicyMisalignmentinPreference-BasedReinforcementLearning,ICML2023Workshop“TheManyFacetsofPreference-BasedLearning”。(其实不太知道workshop是什么概念…)pdf版本:https://arxiv.org/abs/2305.17400html版本:https://ar5iv.labs.arxiv.or......
  • RLHF · PBRL | B-Pref:生成多样非理性 preference,建立 PBRL benchmark
    论文题目:B-Pref:BenchmarkingPreference-BasedReinforcementLearning,2021NeurIPSTrackDatasetsandBenchmarks,778。openreview:https://openreview.net/forum?id=ps95-mkHF_pdf版本:https://arxiv.org/pdf/2111.03026.pdfhtml版本:https://ar5iv.labs.arxiv.org/ht......
  • Windows PBR Reset在62%处不动
    晚上在调查一个问题,需要做WindowsPBRReset,Windows的版本号是22621.2751在启动PBRReset时,一直停留在62%的进度条上(图片忘记保存了)我想通过重启系统来解决,可是重启过程也被卡住了。于是,我尝试着做WindowsUpdate,将系统更新到最新的状态,果然,完成WindowsUpdate之后,PBRReset就......
  • Cocos Creator 3.0基于PBR的物理渲染详解
    CocosCreator3.0出来以后,终于CocosCreator升级成为全新的2D/3D游戏引擎,适合2D和3D游戏开发,而3D游戏对画面效果和渲染管线的定制会有很高的需求,PBR美术工作流作为次世代主流的解决方案,今天我们来详细的分析一下基于CocosCreator的PBR物理渲染。1:计算机是如何显示颜色的讨......
  • RLHF · PBRL | 发现部分 D4RL tasks 不适合做 offline reward learning 的 benchmark
    论文题目:BenchmarksandAlgorithmsforOfflinePreference-BasedRewardLearning,TMLR20230103发表。openreview:https://openreview.net/forum?id=TGuXXlbKsnpdf版本:https://arxiv.org/pdf/2301.01392.pdfhtml版本:https://ar5iv.labs.arxiv.org/html/2301.01392目......
  • RLHF · PBRL | SURF:使用半监督学习,对 labeled segment pair 进行数据增强
    论文名称:SURF:Semi-supervisedrewardlearningwithdataaugmentationforfeedback-efficientpreference-basedreinforcementlearning,ICLR2022,分数666接收,又是PieterAbbeel组的(恼)。(最近的readinglist里全是他们组的文章,已经读过了PEBBLE和RUNE并撰写阅读......