jjzjj

Unity-默认渲染管线-刻晴卡渲shader

TingQiaoQiao 2024-02-27 原文

1.1贴图

共使用以上7张贴图,分别是面部阴影贴图、身体颜色贴图、头发颜色贴图、参数贴图、ramp texture、参数贴图、脸部颜色贴图。

1.2Pass

该shader主要有三个pass,分别是角色主要颜色和光照输出的结果,轮廓边,阴影输出。

1.3光照

 

1.4分支

身体、脸部、头发三个分支

//分支声明
#pragma shader_feature __  _SHADERENUM_BASE _SHADERENUM_FACE _SHADERENUM_HAIR

1.5采样ramp贴图方法

            //ramptexture 采样函数
            float3 NPR_Ramp(float NdotL) {

                float halfLambertRamp = smoothstep(0.0, 0.5, NdotL * 0.5 + 0.5);

                if(_InNight > 0.0){
                    float3 var_rampTex = tex2D(_RampTex, float2(halfLambertRamp, _RampMapYRange));
                    return var_rampTex;
                }
                else {
                    float3 var_rampTex = tex2D(_RampTex, float2(halfLambertRamp, _RampMapYRange + 0.5));
                    return var_rampTex;
                }

            }

用的是半兰伯特光照模型,因为是将(半兰伯特模型所得到的结果,所需采样的颜色参数)作为uv坐标来对贴图进行采样,从而可以达到实现不同的颜色效果。

1.6采样高光贴图方法

            //specular
            float NPR_Specular(float HdotN, float4 var_ParamTex, float3 baseCol) {

                //不同分支用不同的高光贴图
#if defined(_SHADERENUM_HAIR)
                float specularPow = pow(HdotN, var_ParamTex.a * _SpecularPow);
#else
                float specularPow = pow(HdotN, var_ParamTex.r * _SpecularPow);
#endif

                float3 specularCol = var_ParamTex.b * baseCol;  //主颜色乘阴影

#if defined(_SHADERENUM_HAIR)
                float specular = smoothstep(0.4, 0.5, specularPow) * lerp(_SpecularInt, 1.0, var_ParamTex.b) * specularCol ;
                return specular;
#else
                float specular = smoothstep(0.4, 0.5, specularPow) * var_ParamTex.b * specularCol;
                return specular;
#endif
            }

用的是Blinn-Phong光照模型,参数贴图不同通道贴图如下,分别是高光范围贴图、AO贴图。

 1.7采样金属贴图方法

            //metal
            float3 NPR_Metal(float3 nDirVS, float4 var_ParamTex, float3 baseCol) {
                float2 mapUV = nDirVS.rg * 0.5 + 0.5;
                float3 var_matcap = tex2D(_Matcap, mapUV);

#if defined(_SHADERENUM_HAIR)
                float3 metalCol = var_matcap * baseCol * var_ParamTex.a;
                return metalCol;
#else
                float3 metalCol = var_matcap * baseCol * var_ParamTex.r;
                return metalCol;
#endif
            }

  1.8边缘光方法

            //边缘光,用菲尼尔
            float3 NPR_Rim(float3 VdotN, float3 NdotL, float3 baseCol) {
                float3 light = 1 - (NdotL * 0.5 + 0.5);
                float3 rim = (1.0 - smoothstep(_RimPow, _RimPow + 0.03, VdotN) * _RinInt * light) * baseCol ;
                return rim;
            }

  1.9自发光方法

            //自发光
            float3 NPR_emissionCol(float emissionTex, float3 baseCol) {
                float3 emission = emissionTex * _EmissionInt * baseCol * abs((frac(_Time.y * 0.5) - 0.5) * _EmissionSpeed);
                return emission;
            }

  1.10面部阴影方法

            //脸部
            float3 NRF_FaceShadow(float ndotl, float3 baseCol, float var_FaceShadowTex, float3 lDir) {
                float3 Up = float3(0.0, 1.0, 0.0);
                float3 Front = unity_ObjectToWorld._12_22_32;
                float3 Right = cross(Up, Front);
                float2 rightXZ = normalize(Right.xz);
                float2 lDirXZ = normalize(lDir.xz);
                float switchShadow = dot(rightXZ, lDirXZ) * 0.5 + 0.5 < 0.5;
                float FaceShadow = lerp(var_FaceShadowTex, 1- var_FaceShadowTex, switchShadow) ;
                float frontXZ = normalize(Front.xz);
                float FaceShadowRange = dot(frontXZ, lDirXZ);
                float lightAttenuation = 1 - smoothstep(FaceShadowRange - _FaceShadowRangeSmooth, FaceShadowRange + _FaceShadowRangeSmooth, FaceShadow);
                float3 rampCol = NPR_Ramp(lightAttenuation *(ndotl * 5), _RampMapYRange)+0.35;
                float3 faceCol = rampCol * baseCol + ndotl * 0.1;
                
                return faceCol;
            }

所采样的贴图为下图,因为通过判断所计算光与模型右边的点积得到结果数值,从而改变uv采样坐标,得到不同方向光照下对阴影贴图的取样结果。

 2.1控制全局光照参数脚本

using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;

public class lightingcontrollor : MonoBehaviour
{

        public float _RampMapYRange = 0.3f;
        public float _SpecularPow = 50.0f;
        public float _SpecularInt = 2.0f;
        public float _RimPow = 1.0f;
        public float _RinInt = 1.0f;
        public float _EmissionInt = 2.0f;
        public float _EmissionSpeed = 2.0f;
        public float _FaceShadowRangeSmooth = 0.1f;

        public float _OutlineWidth = 0.0001f;
        public Color _OutlineCol = Color.black;


    private void OnEnable()
    {
        UpdateGlobalProperties();
    }

    public void UpdateGlobalProperties()
    {
        Shader.SetGlobalFloat("_RampMapYRange", _RampMapYRange);
        Shader.SetGlobalFloat("_SpecularPow", _SpecularPow);
        Shader.SetGlobalFloat("_SpecularInt", _SpecularInt);
        Shader.SetGlobalFloat("_RimPow", _RimPow);
        Shader.SetGlobalFloat("_RinInt", _RinInt);
        Shader.SetGlobalFloat("_EmissionInt", _EmissionInt);
        Shader.SetGlobalFloat("_EmissionSpeed", _EmissionSpeed);
        Shader.SetGlobalFloat("_FaceShadowRangeSmooth", _FaceShadowRangeSmooth);
        Shader.SetGlobalFloat("_OutlineWidth", _OutlineWidth);
        Shader.SetGlobalColor("_OutlineCol", _OutlineCol);
    }

 3.1脚本GUI

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(lightingcontrollor))]
public class lightingcontrollorGUI : Editor
{
    // 重载GUI绘制方法
    public override void OnInspectorGUI()
    {
        // 获取控制器
        var controller = target as lightingcontrollor;
        // 判空
        if (controller == null) return;

        // 绘制参数面板区
        DrawGlobalProperties(controller);
    }

    // 组开关变量
    private bool _groupAToggle;
    private bool _groupBToggle;

    private void DrawGlobalProperties(lightingcontrollor controller)
    {
        EditorGUI.BeginChangeCheck();
        {
            // 参数组A: 光照参数配置
            _groupAToggle = EditorGUILayout.BeginFoldoutHeaderGroup(_groupAToggle, "光照参数配置");
            if (_groupAToggle)
            {
                controller._RampMapYRange = EditorGUILayout.Slider(
                    "RampTexture采样颜色",
                    controller._RampMapYRange,
                    0.0f, 0.5f);

                controller._SpecularPow = EditorGUILayout.Slider(
                    "高光次幂",
                    controller._SpecularPow,
                    10.0f, 200.0f);

                controller._SpecularInt = EditorGUILayout.Slider(
                    "高光强度",
                    controller._SpecularInt,
                    0.0f, 5.0f);

                controller._RimPow = EditorGUILayout.Slider(
                    "边缘光幂",
                    controller._RimPow,
                    0.0f, 2.0f);

                controller._RinInt = EditorGUILayout.Slider(
                    "边缘光强度",
                    controller._RinInt,
                    0.0f, 0.5f);

                controller._EmissionInt = EditorGUILayout.Slider(
                    "自发光强度",
                    controller._EmissionInt,
                    1.0f, 5.0f);

                controller._EmissionSpeed = EditorGUILayout.Slider(
                    "发光频率",
                    controller._EmissionSpeed,
                    1.0f, 4.0f);

                controller._FaceShadowRangeSmooth = EditorGUILayout.Slider(
                    "面部阴影模糊程度",
                    controller._FaceShadowRangeSmooth,
                    0.1f, 1.0f);
            }
            EditorGUILayout.EndFoldoutHeaderGroup();


            // 参数组B: 描边参数配置
            _groupBToggle = EditorGUILayout.BeginFoldoutHeaderGroup(_groupBToggle, "描边参数配置");
            if (_groupBToggle)
            {
                controller._OutlineCol = EditorGUILayout.ColorField(
                    "RampTexture采样颜色",
                    controller._OutlineCol);

                controller._OutlineWidth = EditorGUILayout.Slider(
                    "轮廓线宽度",
                    controller._OutlineWidth,
                    0.0001f, 0.0003f);
            }
            EditorGUILayout.EndFoldoutHeaderGroup();
        }

        if (EditorGUI.EndChangeCheck())
        {
            controller.UpdateGlobalProperties();
            EditorUtility.SetDirty(controller);
        }
    }

}

 4.1结果

 

有关Unity-默认渲染管线-刻晴卡渲shader的更多相关文章

  1. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  2. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  3. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  4. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  5. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  8. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  9. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

  10. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

随机推荐